#!/usr/bin/env python
# -*- coding: utf-8

import sys
import anvio.profiler as profiler
import anvio.terminal as terminal

import anvio
from anvio.errors import ConfigError, FilesNPathsError
from anvio.terminal import time_program


__author__ = "Developers of anvi'o (see AUTHORS.txt)"
__copyright__ = "Copyleft 2015-2018, the Meren Lab (http://merenlab.org/)"
__credits__ = []
__license__ = "GPL 3.0"
__version__ = anvio.__version__
__maintainer__ = "A. Murat Eren"
__email__ = "a.murat.eren@gmail.com"
__tags__ = ["metagenomics", "profile_db", "contigs_db", "bam", "variability", "clustering"]
__resources__ = [("The usage of the profiler in metagenomics workflow", "http://merenlab.org/2016/06/22/anvio-tutorial-v2/#anvi-profile")]
__requires__ = ['bam-file', 'contigs-db']
__provides__ = ['single-profile-db', 'misc-data-item-orders']
__description__ = "Creates a single anvi'o profile database. The default input to this program is a BAM file.\
                   When it is run on a BAM file, depending on the user parameters, the program quantifies\
                   coverage per nucleotide position (and averages them out per contig), calculates\
                   single-nucleotide, single-codon, and single-amino acid variants, and stores these data\
                   into appropriate tables. Anvi'o single profiles can be merged by the program `anvi-merge`."


@time_program
def main(args):
    profiler.BAMProfiler(args)._run()


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description=__description__)

    groupI = parser.add_argument_group('INPUTS', 'There are two possible inputs for anvio profiler. You must\
                                                  to declare either of these two.')
    groupI.add_argument('-i', '--input-file', metavar = 'INPUT_BAM', default = None,
                        help = 'Sorted and indexed BAM file to analyze. Takes a long time depending on the\
                                length of the file and parameters used for profiling.')

    groupM = parser.add_argument_group('EXTRAS', 'Things that are not mandatory, but can be useful if/when declared.')
    groupX = parser.add_argument_group('HIERARCHICAL CLUSTERING', "Do you want your splits to be clustered? Yes? No?\
                                        Maybe? Remember: By default, anvi-profile will not perform hierarchical clustering\
                                        on your splits; but if you use `--blank` flag, it will try. You can skip that by\
                                        using the `--skip-hierarchical-clustering` flag.")
    groupQ = parser.add_argument_group('NUMBERS', 'Defaults of these\
                                        parameters will impact your analysis. You can always come back to them\
                                        and update your profiles, but it is important to make sure defaults are\
                                        reasonable for your sample.')
    groupC = parser.add_argument_group('CONTIGS', 'Sweet parameters of convenience')
    groupZ = parser.add_argument_group('PERFORMANCE', 'Performance settings for profiler')

    groupI.add_argument(*anvio.A('contigs-db'), **anvio.K('contigs-db', {'required': False}))
    groupI.add_argument(*anvio.A('blank-profile'), **anvio.K('blank-profile'))
    groupM.add_argument(*anvio.A('output-dir'), **anvio.K('output-dir'))
    groupM.add_argument(*anvio.A('overwrite-output-destinations'), **anvio.K('overwrite-output-destinations'))
    groupM.add_argument(*anvio.A('sample-name'), **anvio.K('sample-name'))
    groupM.add_argument(*anvio.A('report-variability-full'), **anvio.K('report-variability-full'))
    groupM.add_argument(*anvio.A('skip-SNV-profiling'), **anvio.K('skip-SNV-profiling'))
    groupM.add_argument(*anvio.A('profile-SCVs'), **anvio.K('profile-SCVs'))
    groupM.add_argument(*anvio.A('description'), **anvio.K('description'))
    groupX.add_argument(*anvio.A('cluster-contigs'), **anvio.K('cluster-contigs'))
    groupX.add_argument(*anvio.A('skip-hierarchical-clustering'), **anvio.K('skip-hierarchical-clustering'))
    groupX.add_argument(*anvio.A('distance'), **anvio.K('distance', {'help':
                            'The distance metric for the hierarchical clustering. Only relevant if you are\
                             using `--cluster-contigs` flag. The default is "%(default)s".'}))
    groupX.add_argument(*anvio.A('linkage'), **anvio.K('linkage', {'help':
                            'The linkage method for the hierarchical clustering. Just like the distance metric\
                             this is only relevant if you are using it with `--cluster-contigs` flag. The\
                             default is "%(default)s".'}))
    groupQ.add_argument(*anvio.A('min-contig-length'), **anvio.K('min-contig-length'))
    groupQ.add_argument(*anvio.A('max-contig-length'), **anvio.K('max-contig-length'))
    groupQ.add_argument(*anvio.A('min-mean-coverage'), **anvio.K('min-mean-coverage'))
    groupQ.add_argument(*anvio.A('min-coverage-for-variability'), **anvio.K('min-coverage-for-variability'))
    groupC.add_argument(*anvio.A('list-contigs'), **anvio.K('list-contigs'))
    groupC.add_argument(*anvio.A('contigs-of-interest'), **anvio.K('contigs-of-interest'))
    groupZ.add_argument(*anvio.A('num-threads'), **anvio.K('num-threads'))
    groupZ.add_argument(*anvio.A('queue-size'), **anvio.K('queue-size'))
    groupZ.add_argument(*anvio.A('write-buffer-size-per-thread'), **anvio.K('write-buffer-size-per-thread'))
    groupZ.add_argument('--force-multi', action='store_true',
                        help="This is not useful to non-developers. It forces the multi-process "
                             "routine even when 1 thread is chosen.")

    args = anvio.get_args(parser)

    try:
        main(args)
    except ConfigError as e:
        print(e)
        sys.exit(-1)
    except FilesNPathsError as e:
        print(e)
        sys.exit(-1)
