#!/usr/bin/env python3
# Daniel B. Stribling
# Renne Lab, University of Florida
# Hybkit Project : http://www.github.com/RenneLab/hybkit

r"""
Read one or more hyb (and optional fold) format files and check for errors.

This utility reads in one or more files in hyb-format
(see the :ref:`Hybkit Hyb File Specification`)
and uses hybkit's internal file error checking to check for errors. This can be useful
as an initial preparation step for further analyses.

Example system calls:
    ::

        hyb_check -i my_file_1.hyb -f my_file_1.vienna
        hyb_check -i my_file_1.hyb my_file_2.hyb -f my_file_1.vienna \\
            my_file_2.vienna -v --custom_flags myflag


"""

import argparse
import contextlib
import os
from typing import List, Optional, Union

import hybkit
from hybkit.__about__ import (
    __author__,
    __contact__,
    __credits__,
    __date__,
    __deprecated__,
    __email__,
    __license__,
    __maintainer__,
    __status__,
    __version__,
)

# ----- Linting Directives:
# ruff: noqa: F401 SLF001

# Create Command-line Argument Parser
def make_parser() -> argparse.ArgumentParser:
    """Create and return the argparse.ArgumentParser for the hyb_check script."""
    parser_components = [
        hybkit.util.in_hybs_parser,
        hybkit.util.in_folds_parser,
        hybkit.util.gen_opts_parser,
        hybkit.util.cmb_hyb_fold_class_settings_parser,
    ]

    script_parser = argparse.ArgumentParser(
        parents=parser_components,
        prog='hyb_check',
        description=hybkit.util.get_argparse_doc(__doc__),
        epilog=hybkit.util.output_description,
        formatter_class=hybkit.util._HybkitFormatter,
        allow_abbrev=False,
    )

    return script_parser


# Define main script function.
def hyb_check(
        in_hyb_files: List[str],
        in_fold_files: Optional[List[str]] = None,
        verbose: bool = False,
        silent: bool = False,
        ) -> None:
    """Perform main script function."""
    if not silent:
        print('\nChecking Hyb and Fold Files...')

    # Start Setup Input / Output Files
    if in_fold_files:
        file_iter = zip(in_hyb_files, in_fold_files)
    else:
        file_iter = in_hyb_files

    for _i, use_files in enumerate(file_iter):
        if in_fold_files:
            in_hyb_file, in_fold_file = use_files
        else:
            in_hyb_file, in_fold_file = use_files, None
        file_basename = os.path.basename(in_hyb_file)
        _file_label = file_basename.replace('.hyb', '')

        if in_fold_file is not None:
            if any(in_fold_file.endswith(s) for s in hybkit.settings.VIENNA_SUFFIXES):
                in_fold_class = hybkit.ViennaFile
            elif any(in_fold_file.endswith(s) for s in hybkit.settings.CT_SUFFIXES):
                in_fold_class = hybkit.CtFile
            else:
                raise ValueError('Unrecognized fold file type: %s' % in_fold_file)
            in_fold_args = (in_fold_file, 'r')
        else:
            in_fold_class = contextlib.nullcontext
            in_fold_args = ()

        if verbose:
            print('Checking Files:')
            print('    Input Hyb:   ' + in_hyb_file)
            if in_fold_files:
                print('    Input Fold:  ' + in_fold_file)

        # Start Record Iteration
        with hybkit.HybFile(in_hyb_file, 'r') as in_hyb, \
             in_fold_class(*in_fold_args) as in_fold:
            if in_fold_file is None:
                record_iter = in_hyb
            else:
                record_iter = hybkit.HybFoldIter(in_hyb, in_fold, combine=True)

            for _j, _hyb_record in enumerate(record_iter, start=1):
                pass

    if verbose:
        if hasattr(record_iter, 'print_report'):
            print('\nHybFoldIter Report:\n')
            record_iter.print_report()
        print('\nError Checking Complete.\n')


# Execute the script function
if __name__ == '__main__':
    script_parser = make_parser()
    args = script_parser.parse_args()
    hybkit.util.validate_args(args, script_parser)
    hybkit.util.set_settings_from_namespace(args, verbose=args.verbose)
    hyb_check(
        in_hyb_files=args.in_hyb,
        in_fold_files=args.in_fold,
        verbose=args.verbose,
        silent=args.silent,
    )
