import argparse
import sys

from pathlib import Path

from seal.analyze import main as analyze_main
from seal.misc import add_coord_cols, add_date_col, check_quadrat_list, convert_aopk, convert_biolib, join_analyses
from seal.plot import main as plot_main
from seal.preprocess import main as preprocess_main


def main(argv=sys.argv):
    parser = argparse.ArgumentParser(
        prog='seal',
        description='Process and visualize influence of grain and extent on perceived species richness and species-area relationships',
    )
    subparsers = parser.add_subparsers(title='Subcommands', required=True)

    analyze = subparsers.add_parser(
        'analyze',
        description='Calculate data necessary to plot various curves from an encounters dataset. \
        May output additional potentially relevant data.',
    )
    analyze.add_argument('-t', '--taskfile', required=True, type=Path, help='path to taskfile')
    analyze.set_defaults(func=analyze_main)

    plot = subparsers.add_parser('plot', description='Plot data generated by seal-analyze.')
    plot.add_argument('-t', '--taskfile', type=Path, required=True, help='path to taskfile')
    plot.add_argument('-j', '--joined', nargs=2, help='type of joined analysis and path to its data')
    plot.add_argument('--png', action='store_true', help='save resulting graphs as .png instead of .svg')
    plot.set_defaults(func=plot_main)

    prepr = subparsers.add_parser(
        'preprocess',
        description='''Checks and cleans datasets intended for analysis of influence of grain and extent on perceived species richness.
            Data that satisfy all specified conditions will be written to [OUTPUT].''',
    )
    full_checklist = [
        'dups',
        'coords',
        'family',
        'morph-species',
        'nas',
        'quartets',
        'refs',
        'strs',
        'species-name',
        'species-phase-morph',
    ]
    default_checklist = ['dups', 'nas', 'strs']
    prepr.add_argument(
        '-c',
        '--checks',
        choices=full_checklist,
        default=default_checklist,
        nargs='+',
        help='''Checks to perform:
        \tdups: Check for potential duplicates (does not filter them automatically)
        \tcoords: Check that coordinates correspond to quadrat_id
        \tfamily: Labridae and Scaridae families should not exist in "ad" phase, ("term" phase is acceptable)
        \tmorph-species: Morph attributes not starting with "M " should be equal to species
        \tnas: Warn for missing values in dataset
        \tspecies-name: species and name should only ever exist in one combination
        \tspecies-phase-morph: species and phase combination should only ever belong to a sigle morph
        \trefs: Ref should be arithmetic progression with a1=1 and d=1
        \tstrs: Only permitted whitespace are simple nonconsecutive spaces
        ''',
    )
    prepr.add_argument(
        '--drop-nas',
        action=argparse.BooleanOptionalAction,
        help='Set automatic action for dealing with missing values without prompting for user input.',
    )
    prepr.add_argument('--dataset', type=Path, help='Path to encounters dataset.')
    prepr.add_argument('--output', type=Path, help='Filename (incl. suffix) where result will be written.')
    prepr.set_defaults(func=preprocess_main)

    misc = subparsers.add_parser('misc')
    misc_subparsers = misc.add_subparsers(title='Subcommands', required=True)

    dcol = misc_subparsers.add_parser(
        'add-date-col', description='Add ISO 8601-formatted date column to encounters dataset.'
    )
    dcol.add_argument('dataset', type=Path, help='Path to encounters dataset.')
    dcol.add_argument('output', type=Path, nargs='?', help='Output filename.')
    dcol.set_defaults(func=add_date_col)

    qlist_check = misc_subparsers.add_parser('check-quadrat-list', description='Quadrat list sanity checks.')
    qlist_check.add_argument('quadrat_list', type=Path, help='Path to quadrat list.')
    qlist_check.add_argument('output', type=Path, nargs='?', help='Output filename.')
    qlist_check.set_defaults(func=check_quadrat_list)

    coord_cols = misc_subparsers.add_parser(
        'add-coord-cols', description='Add coordinates to quadrat list based on their ID.'
    )
    coord_cols.add_argument('quadrat_list', type=Path, help='Path to quadrat list.')
    coord_cols.add_argument('output', type=Path, nargs='?', help='Output filename.')
    coord_cols.set_defaults(func=add_coord_cols)

    a_join = misc_subparsers.add_parser('join-analyses', description='Join multiple analyses of the same type.')
    a_join.add_argument(
        '--discriminants',
        type=str,
        required=False,
        nargs='+',
        help='Add a column with set values to tell merged analyses apart.',
    )
    a_join.add_argument('--inputs', type=Path, nargs='+', help='Paths to analysis results.')
    a_join.add_argument('--output', type=Path, help='Output filename.')
    a_join.set_defaults(func=join_analyses)

    biolib = misc_subparsers.add_parser(
        'convert-biolib', description='Convert BioLib data for preprocessi and analysis.'
    )
    biolib.add_argument('input', type=Path, help='Paths dataset obtained from BioLib.')
    biolib.add_argument('output', type=Path, help='Output filename.')
    biolib.set_defaults(func=convert_biolib)

    aopk = misc_subparsers.add_parser('convert-aopk', description='Convert AOPK data for preprocessing and analysis.')
    aopk.add_argument('input', type=Path, help='Paths dataset obtained from AOPK.')
    aopk.add_argument('output', type=Path, help='Output filename.')
    aopk.set_defaults(func=convert_aopk)

    args = parser.parse_args(argv[1:])
    args.func(args)


if __name__ == '__main__':
    sys.exit(main(sys.argv))
