# -*- coding: utf-8
# pylint: disable=line-too-long

"""Lots of under-the-rug, operational garbage in here. Run. Run away.."""

import os
import sys
import copy
import pkg_resources


# Make sure the Python environment hasn't changed since the installation (happens more often than you'd think
# on systems working with multiple Python installations that are managed through modules):
try:
    if sys.version_info.major != 3:
        sys.stderr.write("Your active Python major version ('%d') is not compatible with what anvi'o expects :/ We recently switched to Python 3.\n" % sys.version_info.major)
        sys.exit(-1)
except Exception:
    sys.stderr.write("(anvi'o failed to learn about your Python version, but it will pretend as if nothing happened)\n\n")


import anvio.tables as tables
import anvio.constants as constants


# a comprehensive arguments dictionary that provides easy access from various programs that interface anvi'o modules:
D = {
    'profile-db': (
            ['-p', '--profile-db'],
            {'metavar': "PROFILE_DB",
             'required': True,
             'help': "Anvi'o profile database"}
                ),
    'pan-db': (
            ['-p', '--pan-db'],
            {'metavar': "PAN_DB",
             'required': True,
             'help': "Anvi'o pan database"}
                ),
    'pan-or-profile-db': (
            ['-p', '--pan-or-profile-db'],
            {'metavar': "PAN_OR_PROFILE_DB",
             'required': True,
             'help': "Anvi'o pan or profile database"}
                ),
    'genomes-storage': (
            ['-g', '--genomes-storage'],
            {'metavar': "GENOMES_STORAGE",
             'required': False,
             'help': "Anvi'o genomes storage file"}
                ),
    'genomes-names': (
            ['-G', '--genome-names'],
            {'metavar': "GENOME_NAMES",
             'required': False,
             'help': "Genome names to 'focus'. You can use this parameter to limit the genomes included in your analysis.\
                      You can provide these names as a commma-separated list of names, or you can put them in a file,\
                      where you have a single genome name in each line, and provide the file path."}
                ),
    'serialized-profile': (
            ['-d', '--serialized-profile'],
            {'metavar': "PROFILE",
             'help': "Serialized profile (PROFILE.cp). You can use anvi'o serialized profile files to re-do the\
                      profiling much more quickly. This file is generated only if it is requested during the\
                      initial profiling of the BAM file. See '--gen-serialized-profile' flag for details."}
                ),
    'blank-profile': (
            ['--blank-profile'],
            {'default': False,
             'action': 'store_true',
             'help': "If you only have contig sequences, but no mapping data (i.e., you found a genome and would like to\
                      take a look from it), this flag will become very hand. After creating a contigs database for your\
                      contigs, you can create a blank anvi'o profile database to use anvi'o interactive\
                      interface with that contigs database without any mapping data."}
                ),
    'samples-information-db': (
            ['-s', '--samples-information-db'],
            {'metavar': 'SAMPLES_DB',
             'help': "Samples information database generated by 'anvi-gen-samples-info-database'"}
                ),
    'contigs-db': (
            ['-c', '--contigs-db'],
            {'metavar': 'CONTIGS_DB',
             'required': True,
             'help': "Anvi'o contigs database generated by 'anvi-gen-contigs'"}
                ),
    'runinfo': (
            ['-r', '--runinfo'],
            {'metavar': 'RUNINFO_PATH',
             'required': True,
             'help': "Anvi'o runinfo file path."}
                ),
    'description': (
            ['--description'],
            {'metavar': 'TEXT_FILE',
             'required': False,
             'help': "A plain text file that contains some description about the project. You can use Markdwon syntax.\
                      The description text will be rendered and shown in all relevant interfaces, including the\
                      anvi'o interactive interface, or anvi'o summary outputs."}
                ),

    'additional-view': (
            ['-V', '--additional-view'],
            {'metavar': 'ADDITIONAL_VIEW',
             'help': "A TAB-delimited file for an additional view to be used in the interface. This\
                      file file should contain all split names, and values for each of them in all\
                      samples. Each column in this file must correspond to a sample name. Content\
                      of this file will be called 'user_vuew', which will be available as a new item\
                      in the 'views' combo box in the interface"}
                ),
    'fasta-file': (
            ['-f', '--fasta-file'],
            {'metavar': 'FASTA',
             'help': "A FASTA-formatted input file"}
                ),
    'samples-information-file': (
            ['-D', '--samples-information-file'],
            {'metavar': 'FILE',
             'help': "A TAB-delimited file with information about samples in your dataset. Each row in this\
                      file must correspond to a sample name. Each column must contain a unique attribute.\
                      Please refer to the documentation to learn more about the structure and purpose of\
                      this file."}
                ),
    'samples-order-file': (
            ['-R', '--samples-order-file'],
            {'metavar': 'FILE',
             'help': "A TAB-delimited file with three columns: 'attribute', 'basic', 'newick'. For each attribute,\
                      the order of samples must be defined either in the 'basic' form or via a 'newick'-formatted\
                      tree structurei that describes the organization of each sample. Anvi'o will look for a\
                      comma-separated list of sample names for the 'basic' form. Please refer to the online docs\
                      for more info. Also you shouldn't hesitate to try to find the right file format until you get\
                      it working. There are stringent checks on this file, and you will not break anything while trying!."}
                ),
    'single-order-file': (
            ['-r', '--single-order-file'],
            {'metavar': 'FILE',
             'help': "A file with a single samples order. It could be a newick formatted tree, or it could be an array.\
                      But when you use this parameter, you must also use the parameter `--order-name` to give it a name."}
                ),
    'order-name': (
            ['-n', '--order-name'],
            {'metavar': 'NAME',
             'help': "A name for your single order. It better be a simple name without fancy characters or space."}
                ),
    'split-length': (
            ['-L', '--split-length'],
            {'metavar': 'INT',
             'default': 20000,
             'type': int,
             'help': "Splitting very large contigs into multiple pieces improves the efficacy of the\
                      visualization step. The default value is (%(default)d). If you are not sure, we\
                      advise you to not go below 10,000. The lower you go, the more complicated the\
                      tree will be, and will take more time and computational resources to finish the\
                      analysis. Also this is not a case of 'the smaller the split size the more sensitive\
                      the results'. If you do not want your contigs to be split, you can either simply\
                      enter '0' or ANY OTHER negative integer (lots of unnecessary freedom here, enjoy!)."}
                ),
    'kmer-size': (
            ['-K', '--kmer-size'],
            {'metavar': 'INT',
             'default': 4,
             'type': int,
             'help': "K-mer size for k-mer frequency calculations. The default k-mer size for composition-based\
                      analyses is 4, historically. Although tetra-nucleotide frequencies seem to offer the\
                      the sweet spot of sensitivity, information density, and manageable number of dimensions\
                      for clustering approaches, you are welcome to experiment (but maybe you should leave\
                      it as is for your first set of analyses)."}
                ),
    'skip-gene-calling': (
            ['--skip-gene-calling'],
            {'default': False,
             'action': 'store_true',
             'help': "By default, generating an anvi'o contigs database includes the identification of open reading\
                      frames in contigs by running a bacterial gene caller. Declaring this flag will by-pass that\
                      process. If you prefer, you can later import your own gene calling results into the database."}
                ),
    'external-gene-calls': (
            ['--external-gene-calls'],
            {'metavar': 'GENE-CALLS',
             'help': "A TAB-delimited file to utilize external gene calls. The file must have these columns: 'gene_callers_id'\
                      (a unique integer number for each gene call, start from 1), 'contig' (the contig name the gene call is found),\
                      'start' (start position, integer), 'stop' (stop position, integer), 'direction' (the direction of the gene open reading\
                      frame; can be 'f' or 'r'), 'partial' (whether it is a complete gene call, or a partial one; must be 1 for partial\
                      calls, and 0 for complete calls), 'source' (the gene caller), and 'version' (the version of the gene caller, i.e.,\
                      v2.6.7 or v1.0). An example file can be found via the URL https://goo.gl/TqCWT2"}
                ),
    'external-genomes': (
            ['-e', '--external-genomes'],
            {'metavar': 'FILE_PATH',
             'help': "A two-column TAB-delimited flat text file that lists anvi'o contigs databases. The first item\
                      in the header line should read 'name', and the second should read 'contigs_db_path'. Each line in the\
                      file should describe a single entry, where the first column is the name of the genome (or MAG), and\
                      the second column is the anvi'o contigs database generated for this genome."}
                ),
    'internal-genomes': (
            ['-i', '--internal-genomes'],
            {'metavar': 'FILE_PATH',
             'help': "A four-column TAB-delimited flat text file. The header line must contain thse columns: 'name', 'bin_id',\
                      'collection_id', 'profile_db_path', 'contigs_db_path'. Each line should list a single entry, where 'name'\
                      can be any name to describe the anvi'o bin identified as 'bin_id' that is stored in a collection."}
                ),
    'gene-caller': (
            ['--gene-caller'],
            {'metavar': 'GENE-CALLER',
             'help': "The gene caller to utilize. Anvi'o supports multiple gene callers, and some operations (including this one)\
                      requires an explicit mentioning of which one to use. The default is '%s', but it will not be enough if you\
                      if you were a rebel adn have used `--external-gene-callers` or something." % constants.default_gene_caller}
                ),

    'ignore-internal-stop-codons': (
            ['--ignore-internal-stop-codons'],
            {'default': False,
             'action': 'store_true',
             'help': "This is only relevant when you have an external gene calls file. If anvi'o figures out that your custom gene calls\
                      result in amino acid seqeunces with stop codons in the middle, it will complain about it. You can use this flag\
                      to tell anvi'o to don't check for internal stop codons, EVEN THOUGH IT MEANS THERE IS MOST LIKELY SOMETHING\
                      WRONG WITH YOUR EXTERNAL GENE CALLS FILE. Anvi'o will understand that sometimes we don't want to care, and will\
                      not judge you. Instead, it will replace every stop codon residue in the amino acid sequence with an 'X' character.\
                      Please let us know if you used this and things failed, so we can tell you that you shouldn't have really used it\
                      if you didn't like failures at the first place (smiley)."}
                ),
    'skip-SNV-profiling': (
            ['--skip-SNV-profiling'],
            {'default': False,
             'action': 'store_true',
             'help': "By default, anvi'o characterizes single-nucleotide variation in each sample. The use of this flag\
                      will instruct profiler to skip that step. Please remember that parameters and flags must be\
                      identical between different profiles using the same contigs database for them to merge properly."}
                ),
    'profile-AA-frequencies': (
            ['--profile-AA-frequencies'],
            {'default': False,
             'action': 'store_true',
             'help': "Anvi'o can characterize linkmer frequencies for AA distribution in genes in contigs during\
                      profiling. However, due to its computational complexity, this feature is by default off. Using\
                      this flag you can go against the authority, and make anvi'o do it. Please remember that this\
                      functionality is available only if genes calls are present in contigs database."}
                ),
    'drop-previous-annotations': (
            ['--drop-previous-annotations'],
            {'default': False,
             'action': 'store_true',
             'help': "Use this flag if you want anvi'o to remove ALL previous functional annotations for your genes,\
                      and then import the new data. The default behavior will add any annotation source into the db\
                      incrementally unless there are already annotations from this source. In which case, it will first\
                      remove previous annotations for that source only (i.e., if source X is both in the db and in the\
                      incoming annotations data, it will replace the content of source X in the db)."}
                ),
    'skip-mindful-splitting': (
            ['--skip-mindful-splitting'],
            {'default': False,
             'action': 'store_true',
             'help': "By default, anvi'o attempts to prevent soft-splitting large contigs by cutting prper gene calles\
                      to make sure a single gene is not broken into multiple splits. This requires a careful\
                      examination of where genes start and end, and to find best locations to split contigs with respect\
                      to this informtion. So, when the user asks for a split size of, say, 1,000, it serves as a\
                      mere suggestion. When this flag is used, anvi'o does what the user wants and creates splits at\
                      desired lengths (although some functionality may become unavailable for the projects that rely on\
                      a contigs database that is initiated this way)."}
                ),
    'contigs-fasta': (
            ['-f', '--contigs-fasta'],
            {'metavar': 'FASTA',
             'required': True,
             'help': "The FASTA file that contains reference sequences you mapped your samples against. This\
                      could be a reference genome, or contigs from your assembler. Contig names in this file\
                      must match to those in other input files. If there is a problem anvi'o will gracefully\
                      complain about it."}
                ),
    'view-data': (
            ['-d', '--view-data'],
            {'metavar': 'VIEW_DATA',
             'help': "A TAB-delimited file for view data"}
                ),
    'tree': (
            ['-t', '--tree'],
            {'metavar': 'NEWICK',
             'help': "NEWICK formatted tree structure"}
                ),
    'additional-layers': (
            ['-A', '--additional-layers'],
            {'metavar': 'ADDITIONAL_LAYERS',
             'help': "A TAB-delimited file for additional layers for splits. The first column of this file\
                      must be split names, and the remaining columns should be unique attributes.\
                      The file does not need to contain all split names, or values for each split in\
                      every column. Anvi'o will try to deal with missing data nicely. Each column in this\
                      file will be visualized as a new layer in the tree."}
                ),
    'view': (
            ['--view'],
            {'metavar': 'NAME',
             'help': "Start the interface with a pre-selected view. To see a list of available views,\
                      use --show-views flag."}
                ),
    'table': (
            ['--table'],
            {'metavar': 'TABLE_NAME',
             'help': "Table name to export."}
                ),
    'fields': (
            ['-f', '--fields'],
            {'metavar': 'FIELD(S)',
             'help': "Fields to report. USe --list-tables parameter with a table name to see available\
                      fields  You can list fields using this notation: --fields 'field_1, field_2, ... field_N'."}
                ),
    'list': (
            ['-l', '--list'],
            {'default': False,
             'action': 'store_true',
             'help': "Gives a list of tables in a database and quits. If a table is already declared\
                      this time it lists all the fields in a given table, in case you would to export\
                      only a specific list of fields from the table using --fields parameter."}
                ),
    'title': (
            ['--title'],
            {'metavar': 'NAME',
             'help': "Title for the interface. If you are working with a RUNINFO dict, the title\
                      will be determined based on information stored in that file. Regardless,\
                      you can override that value using this parameter. If you are not using a\
                      anvio RUNINFO dictionary, a meaningful title will appear in the interface\
                      only if you define one using this parameter."}
                ),
    'split-hmm-layers': (
            ['--split-hmm-layers'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, this flag tells the interface to split every gene found in HMM\
                      searches that were performed against non-singlecopy gene HMM profiles into\
                      their own layer. Please see the documentation for details."}
                ),
    'taxonomic-level': (
            ['--taxonomic-level'],
            {'default': 't_genus',
             'type': str,
             'choices': tables.taxon_names_table_structure[1:],
             'help': "The taxonomic level to use. The default is '%(default)s'. Only relevant if the\
                      anvi'o ontigs database contains taxonomic annotations."}
                ),
    'cog-data-dir': (
            ['--cog-data-dir'],
            {'default': None,
             'type': str,
             'help': "The directory path for your COG setup. Anvi'o will try to use the default path\
                      if you do not specify anything."}
                ),
    'hide-outlier-SNVs': (
            ['--hide-outlier-SNVs'],
            {'default': False,
             'action': 'store_true',
             'help': "During profiling, anvi'o marks positions of single-nucleotide variations (SNVs)\
                      that originate from places in contigs where coverage values are a bit 'sketchy'.\
                      If you would like to avoid SNVs in those positions of splits in applicable projects\
                      you can use this flag, and the interafce would hide SNVs that are marked as 'outlier'\
                      (although it is clearly the best to see everything, no one will judge you if you end\
                      up using this flag) (plus, there may or may not be some historical data on this here: \
                      https://github.com/meren/anvio/issues/309)."}
                ),
    'hmm-source': (
            ['--hmm-source'],
            {'metavar': 'SOURCE NAME',
             'help': "Use a specific HMM source. You can use '--list-hmm-sources' flag to see\
                      a list of available resources. The default is '%(default)s'."}
                ),
    'hmm-sources': (
            ['--hmm-sources'],
            {'metavar': 'SOURCE NAME',
             'help': "Get sequences for a specific list of HMM sources. You can list one or more\
                      sources by separating them from each other with a comma character (i.e., \
                      '--hmm-sources source_1,source_2,source_3'). If you would like to see a list\
                      of available sources in the contigs database, run this program with\
                      '--list-hmm-sources' flag."}
                ),
    'list-hmm-sources': (
            ['-l', '--list-hmm-sources'],
            {'default': False,
             'action': 'store_true',
             'help': "List available HMM sources in the contigs database and quit."}
                ),
    'annotation-sources': (
            ['--annotation-sources'],
            {'metavar': 'SOURCE NAME',
             'default': None,
             'help': "Get functional annotations for a specific list of annotation sources. You\
                      can specifiy one or more sources by separating them from each other with a comma\
                      character (i.e., '--annotation-sources source_1,source_2,source_3'). The default\
                      behavior is to return everything"}
                ),
    'list-annotation-sources': (
            ['-l', '--list-annotation-sources'],
            {'default': False,
             'action': 'store_true',
             'help': "List available sources for annotation in the contigs database and quit."}
                ),
    'gene-names': (
            ['--gene-names'],
            {'metavar': 'HMM HIT NAME',
             'help': "Get sequences only for a specific gene name. Each name should be separated from\
                      each other by a comma character. For instance, if you want to get back only RecA\
                      and Ribosomal_L27, you can type '--gene-names RecA,Ribosomal_L27', and you will\
                      get any and every hit that matches these names in any source. If you would like\
                      to see a list of available gene names, you can use '--list-available-gene-names'\
                      flag."}
                ),
    'get-aa-sequences': (
            ['--get-aa-sequences'],
            {'default': False,
             'action': 'store_true',
             'help': "Store amino acid sequences instead."}
                ),
    'return-best-hit': (
            ['--return-best-hit'],
            {'default': False,
             'action': 'store_true',
             'help': "A bin may contain more than one hit for a gene name in a given HMM source. For instance, there may\
                      be multiple RecA hits in a genome bin from Campbell et al.. Using this flag, will go through all of\
                      the gene names that appear multiple times, and remove all but the one with the lowest e-value. Good\
                      for whenever you really need to get only a single copy of single-copy core genes from a genome bin."}
                ),
    'concatenate-genes': (
            ['--concatenate-genes'],
            {'default': False,
             'action': 'store_true',
             'help': "Concatenate output genes in the same order to create a multi-gene alignment output that is suitable\
                      for phylogenomic analyses."}
                ),
    'separator': (
            ['--separator'],
            {'metavar': 'STRING',
             'default': None,
             'type': str,
             'help': "Characters to separate things (the default is whatever is most suitable)."}
                ),
    'concatenate-pcs': (
            ['--concatenate-pcs'],
            {'default': False,
             'action': 'store_true',
             'help': "Concatenate output PCs in the same order to create a multi-gene alignment output that is suitable\
                      for phylogenomic analyses."}
                ),
    'skip-multiple-gene-calls': (
            ['--skip-multiple-gene-calls'],
            {'default': False,
             'action': 'store_true',
             'help': "When generating concatenated output skip PCs contain multiple gene calls."}
                ),
    'list-available-gene-names': (
            ['-L', '--list-available-gene-names'],
            {'default': False,
             'action': 'store_true',
             'help': "List available gene names in HMM sources selection and quit."}
                ),
    'search-terms': (
            ['--search-terms'],
            {'metavar': 'SEARCH_TERMS',
             'help': "Search terms. Multiple of them can be declared separated by a delimiter (the default is a comma)."}
                ),
    'sensitive': (
            ['--sensitive'],
            {'default': False,
             'action': 'store_true',
             'help': "DIAMOND sensitivity. With this flag you can instruct DIAMOND to be 'sensitive', rather than 'fast'\
                      during the search. It is likely the search will take remarkably longer. But, hey, if you are doing\
                      it for your final analysis, maybe it should take longer and be more accurate. This flag is only\
                      relevant if you are running DIAMOND."}
                ),
    'gene-caller-ids': (
            ['--gene-caller-ids'],
            {'metavar': 'GENE_CALLER_IDS',
             'help': "Gene caller ids. Multiple of them can be declared separated by a delimiter (the default is a comma).\
                      If you declare nothing, you may get everything. Or you may get an error. Really depends on the\
                      situation. Worth a try."}
                ),
    'gene-caller-id': (
            ['--gene-caller-id'],
            {'metavar': 'GENE_CALLER_ID',
             'type': int,
             'help': "A single gene id."}
                ),
    'delimiter': (
            ['--delimiter'],
            {'metavar': 'CHAR',
             'default': ',',
             'help': "The delimiter to parse multiple input terms. The default is '%(default)s'."}
                ),
    'wrap': (
            ['--wrap'],
            {'metavar': 'WRAP',
             'default': 120,
             'type': int,
             'help': "When to wrap sequences when storing them in a FASTA file. The default is\
                      '%(default)d'. A value of '0' would be equivalent to 'do not wrap'."}
                ),
    'leeway': (
            ['--leeway'],
            {'metavar': 'LEEWAY_NTs',
             'default': 100,
             'type': int,
             'help': "The minimum number of nucleotides for a given short read mapping into\
                      the gene context for it to be reported. You must consider the length of\
                      your short reads, as well as the length of the gene you are targeting.\
                      The default is %(default)d nts."}
                ),
    'list-contigs': (
            ['--list-contigs'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the program will list contigs in the BAM file and exit gracefully\
                      without any further analysis."}
                ),
    'list-splits': (
            ['--list-splits'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the program will list split names in the profile database and quite"}
                ),

    'list-collections': (
            ['--list-collections'],
            {'default': False,
             'action': 'store_true',
             'help': "Show available collections and exit."}
                ),
    'list-bins': (
            ['--list-bins'],
            {'default': False,
             'action': 'store_true',
             'help': "List available bins in a collection and exit."}
                ),
    'list-states': (
            ['--list-states'],
            {'default': False,
             'action': 'store_true',
             'help': "Show available states and exit."}
                ),
    'show-views': (
            ['--show-views'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the program will show a list of available views, and exit."}
                ),
    'list-completeness-sources': (
            ['--list-completeness-sources'],
            {'default': False,
             'action': 'store_true',
             'help': "Show available sources and exit."}
                ),
    'completeness-source': (
            ['--completeness-source'],
            {'metavar': 'NAME',
             'help': "Single-copy gene source to use to estimate completeness."}
                ),
    'split-name': (
            ['--split-name'],
            {'metavar': 'SPLIT_NAME',
             'help': "Split name."}
                ),
    'program': (
            ['--program'],
            {'metavar': 'PROGRAM_NAME',
             'help': "Program name.",
             'required': False,
             'default': 'default'}
                ),
    'splits-of-interest': (
            ['--splits-of-interest'],
            {'metavar': 'FILE',
             'help': "A file with split names. There should be only one column in the file, and each line\
                      should correspond to a unique split name."}
                ),
    'contigs-of-interest': (
            ['--contigs-of-interest'],
            {'metavar': 'FILE',
             'help': "It is possible to analyze only a group of contigs from a given BAM file. If you provide\
                      a text file, in which every contig of interest is listed line by line, the profiler would\
                      engine only on those contigs in the BAM file and ignore the rest. This can be used for\
                      debugging purposes, or to engine on a particular group of contigs that were identified as\
                      relevant during the interactive analysis."}
                ),
    'samples-of-interest': (
            ['--samples-of-interest'],
            {'metavar': 'FILE',
             'help': "A file with samples names. There should be only one column in the file, and each line\
                      should correspond to a unique sample name (without a column header)."}
                ),
    'genes-of-interest': (
            ['--genes-of-interest'],
            {'metavar': 'FILE',
             'help': "A file with anvi'o gene caller IDs. There should be only one column in the file, and each line\
                      should correspond to a unique gene caller id (without a column header)."}
                ),
    'pc-id': (
            ['--pc-id'],
            {'metavar': 'PROTEIN_CLUSTER_ID',
             'help': "Protein cluster ID you are interested in."}
                ),
    'pc-ids-file': (
            ['--pc-ids-file'],
            {'metavar': 'FILE_PATH',
             'help': "Text file for protein clusters (each line should contain be a unique protein cluster id)."}
                ),
    'bin-id': (
            ['-b', '--bin-id'],
            {'metavar': 'BIN_NAME',
             'help': "Bin name you are interested in."}
                ),
    'bin-ids-file': (
            ['-B', '--bin-ids-file'],
            {'metavar': 'FILE_PATH',
             'help': "Text file for bins (each line should be a unique bin id)."}
                ),
    'collection-name': (
            ['-C', '--collection-name'],
            {'metavar': 'COLLECTION_NAME',
             'help': "Collection name."}
                ),
    'num-positions-from-each-split': (
            ['--num-positions-from-each-split'],
            {'metavar': 'INT',
             'default': 0,
             'type': int,
             'help': "Each split may have one or more variable positions. By default, anvi'o will report every SNV\
                      position found in a given split. This parameter will help you to define a cutoff for the maximum\
                      number of SNVs to be reported from a split (if the number of SNVs is more than the number you\
                      declare using this parameter, the positions will be randomly subsampled)."}
             ),
    'min-scatter': (
            ['-m', '--min-scatter'],
            {'metavar': 'INT',
             'default': 0,
             'type': int,
             'help': "This one is tricky. If you have N samples in your dataset, a given variable position x in one\
                      of your splits can split your N samples into `t` groups based on the identity of the\
                      variation they harbor at position x. For instance, `t` would have been 1, if all samples had the same\
                      type of variation at position x (which would not be very interesting, because in this case\
                      position x would have zero contribution to a deeper understanding of how these samples differ\
                      based on variability. When `t` > 1, it would mean that identities at position x across samples\
                      do differ. But how much scattering occurs based on position x when t > 1? If t=2, how many\
                      samples ended in each group? Obviously, even distribution of samples across groups may tell\
                      us something different than uneven distribution of samples across groups. So, this parameter\
                      filters out any x if 'the number of samples in the second largest group' (=scatter) is less\
                      than -m. Here is an example: lets assume you have 7 samples. While 5 of those have AG, 2\
                      of them have TC at position x. This would mean scatter of x is 2. If you set -m to 2, this\
                      position would not be reported in your output matrix. The default value for -m is\
                      %(default)d, which means every `x` found in the database and survived previous filtering\
                      criteria will be reported. Naturally, -m can not be more than half of the number of samples.\
                      Please refer to the user documentation if this is confusing."}
                ),
    'min-ratio-of-competings-nts': (
            ['-r', '--min-ratio-of-competings-nts'],
            {'metavar': 'RATIO',
             'default': 0,
             'type': float,
             'help': "Minimum ratio of the competing nucleotides at a given position. Default is %(default)d."}
                ),
    'max-num-unique-positions': (
            ['-n', '--max-num-unique-positions'],
            {'metavar': 'NUM_POSITIONS',
             'default': 0,
             'type': int,
             'help': "Maximum number of unique positions to be used in the network. This may be one way to avoid extremely\
                      large network descriptions that would defeat the purpose of a quick visualization. If there are more\
                      unique positions in the variability profile, the program will randomly select a subset of them to match\
                      the `max-num-unique-positions`. The default is %(default)d, which means all positions should be reported.\
                      Remember that the number of nodes in the network will also depend on the number of samples described in\
                      the variability profile."}
                ),
    'num-threads': (
            ['-T', '--num-threads'],
            {'metavar': 'NUM_CPUS',
             'default': 1,
             'type': int,
             'help': "Maximum number of threads to use for multithreading whenever possible. Very conservatively, the default\
                      is 1. It is a good idea to not exceed the number of CPUs / cores on your system. Plus, please\
                      be careful with this option if you are running your commands on a SGE --if you are clusterizing your runs,\
                      and asking for multiple threads to use, you may deplete your resources very fast."}
                ),

    'min-coverage-in-each-sample': (
            ['--min-coverage-in-each-sample'],
            {'metavar': 'INT',
             'default': 0,
             'type': int,
             'help': "Minimum coverage of a given variable nucleotide position in all samples. If a nucleotide position\
                      is covered less than this value even in one sample, it will be removed from the analysis. Default\
                      is %(default)d."}
                ),
    'min-departure-from-reference': (
            ['-r', '--min-departure-from-reference'],
            {'metavar': 'FLOAT',
             'default': 0,
             'type': float,
             'help': "Takes a value between 0 and 1, where 1 is maximum divergence from the reference. Default is %(default)f.\
                      The reference here observation that corresponds to a given position in the mapped context."}
                ),
    'max-departure-from-reference': (
            ['-z', '--max-departure-from-reference'],
            {'metavar': 'FLOAT',
             'default': 1,
             'type': float,
             'help': "Similar to '--min-departure-from-reference', but defines an upper limit for divergence. The\
                      default is %(default)f."}
                ),
    'min-departure-from-consensus': (
            ['-j', '--min-departure-from-consensus'],
            {'metavar': 'FLOAT',
             'default': 0,
             'type': float,
             'help': "Takes a value between 0 and 1, where 1 is maximum divergence from the consensus for a given position. The\
                      default is %(default)f. The consensus is the most frequent observation at a given positon."}
                ),
    'max-departure-from-consensus': (
            ['-a', '--max-departure-from-consensus'],
            {'metavar': 'FLOAT',
             'default': 1,
             'type': float,
             'help': "Similar to '--min-departure-from-consensus', but defines an upper limit for divergence. The\
                      default is %(default)f."}
                ),
    'min-occurrence-of-variable-positions': (
            ['-x', '--min-occurrence'],
            {'metavar': 'NUM_SAMPLES',
             'default': 1,
             'type': int,
             'help': "Minimum number of samples a nucleotide position should be reported as variable. Default is %(default)d.\
                      If you set it to 2, for instance, each eligable variable position will be expected to appear in at least\
                      two samples, which will reduce the impact of stochastic, or unintelligeable varaible positions."}
                ),
    'quince-mode': (
            ['--quince-mode'],
            {'default': False,
             'action': 'store_true',
             'help': "The default behavior is to report base frequencies of nucleotide positions only if there\
                      is any variation reported during profiling (which by default uses some heuristics to minimize\
                      the impact of error-driven variation). So, if there are 10 samples, and a given position has been\
                      reported as a varaible site during profiling in only one of those samples, there will be no\
                      information will be stored in the database for the remaining 9. When this flag is\
                      used, we go back to each sample, and report base frequencies for each sample at this position\
                      even if they do not vary. It will take considerably longer to report when this flag is on, and the use\
                      of it will increase the file size dramatically, however it is inevitable for some statistical approaches\
                      (as well as for some beautiful visualizations)."}
                ),
    'include-contig-names': (
            ['--include-contig-names'],
            {'default': False,
             'action': 'store_true',
             'help': "Use this flag if you would like contig names for each variable position to be included in the\
                      output file as a column. By default, we do not include contig names since they can practically\
                      double the output file size without any actual benefit in most cases."}
                ),
    'include-split-names': (
            ['--include-split-names'],
            {'default': False,
             'action': 'store_true',
             'help': "Use this flag if you would like split names for each variable position to be included in the\
                      output file as a column."}
                ),
    'engine': (
            ['--engine'],
            {'default': 'NT',
             'metavar': 'ENGINE',
             'type': str,
             'help': "Varaibility engine. The default is '%(default)s'."}
                ),
    'transpose': (
            ['--transpose'],
            {'default': False,
             'action': 'store_true',
             'help': "Transpose the input matrix file before clustering."}
                ),
    'skip-check-names': (
            ['--skip-check-names'],
            {'default': False,
             'action': 'store_true',
             'help': "For debugging purposes. You should never really need it."}
                ),
    'experimental-org-input-dir': (
            ['-i', '--input-directory'],
            {'metavar': 'DIR_PATH',
             'type': str,
             'help': "Input directory where the input files addressed from the configuration\
                      file can be found (i.e., the profile database, if PROFILE.db::TABLE\
                      notation is used in the configuration file)."}
                ),
    'clustering-name': (
            ['-N', '--name'],
            {'metavar': 'NAME',
             'type': str,
             'help': "The name to use when storing the resulting clustering in the database.\
                      This name will appear in the interactive interface and other relevant\
                      interfaces. Please consider using a short and descriptive single-word\
                      (if you do not do that you will make anvi'o complain)."}
                ),
    'distance': (
            ['--distance'],
            {'metavar': 'DISTANCE_METRIC',
             'type': str,
             'default': constants.distance_metric_default,
             'help': "The distance metric for the hierarchical clustering. The default distance\
                      metric is '%(default)s'. You can find the full list of distance metrics\
                      either by making a mistake (such as entering a non-existent distance metric\
                      and making anvi'o upset), or by taking a look at the help menu of the\
                      hierarchy.distance.pdist function in the scipy.cluster module."}
                ),
    'linkage': (
            ['--linkage'],
            {'metavar': 'LINKAGE_METHOD',
             'type': str,
             'default': constants.linkage_method_default,
             'help': "The linkage method for the hierarchical clustering. The default linkage\
                      method is '%(default)s', because that is the best one. It really is. We talked\
                      to a lot of people and they were all like 'this is the best one available' and\
                      it is just all out there. Honestly it is so good that we will build a wall around it\
                      and make other linkage methods pay for it. But if you want to see a full\
                      list of available ones you can check the hierarcy.linkage function in\
                      the scipy.cluster module. Up tp you really. But then you can't use %(default)s\
                      anymore, and you would have to leave anvi'o right now."}
                ),
    'input-dir': (
            ['-i', '--input-dir'],
            {'metavar': 'DIR_PATH',
             'type': str,
             'help': "Directory path for input files"}
                ),
    'output-dir': (
            ['-o', '--output-dir'],
            {'metavar': 'DIR_PATH',
             'type': str,
             'help': "Directory path for output files"}
                ),
    'output-file': (
            ['-o', '--output-file'],
            {'metavar': 'FILE_PATH',
             'type': str,
             'help': "File path to store results."}
                ),
    'log-file': (
            ['--log-file'],
            {'metavar': 'FILE_PATH',
             'type': str,
             'help': "File path to a log output."}
                ),
    'output-db-path': (
            ['-o', '--output-db-path'],
            {'metavar': 'DB_FILE_PATH',
             'type': str,
             'help': "Output file path for the new database."}
                ),
    'temporary-dir-path': (
            ['--temporary-dir-path'],
            {'metavar': 'PATH',
             'type': str,
             'help': "If you don't provide anything here, this program will come up with a temporary\
                      directory path by itself to store intermediate files, and clean it later. If you\
                      want to have full control over this, you can use this flag to define one.."}
                ),
    'output-file-prefix': (
            ['-O', '--output-file-prefix'],
            {'metavar': 'FILENAME_PREFIX',
             'type': str,
             'help': "A prefix to be used while naming the output files (no file type\
                      extensions please; just a prefix)."}
                ),
    'dry-run': (
            ['--dry-run'],
            {'default': False,
             'action': 'store_true',
             'help': "Don't do anything real. Test everything, and stop right before wherever the developer\
                      said 'well, this is enough testing', and decided to print out results."}
                ),
    'verbose': (
            ['--verbose'],
            {'default': False,
             'action': 'store_true',
             'help': "Be verbose, print more messages whenever possible."}
                ),
    'debug': (
            ['--debug'],
            {'default': False,
             'action': 'store_true',
             'help': "Turn on debug messages whenever possible, and skip removing temporary files (this may\
                      cause lots and lots of output, so you may want to not use it if your intention is not\
                      debugging)."}
                ),
    'just-do-it': (
            ['--just-do-it'],
            {'default': False,
             'action': 'store_true',
             'help': "Don't bother me with questions or warnings, just do it."}
                ),
    'ip-address': (
            ['-I', '--ip-address'],
            {'metavar': 'IP_ADDR',
             'type': str,
             'default': '0.0.0.0',
             'help': "IP address for the HTTP server. The default ip address (%(default)s) should\
                      work just fine for most."}
                ),
    'api-url': (
            ['--api-url'],
            {'metavar': 'API_URL',
             'type': str,
             'default': 'https://anvi-server.org',
             'help': "Anvi'server url"}
                ),
    'port-number': (
            ['-P', '--port-number'],
            {'metavar': 'INT',
             'default': None,
             'type': int,
             'help': "Port number to use for anvi'o services. If nothing is declared, anvi'o will try to find\
                      a suitable port number, starting from the default port number, %d." % constants.default_port_number}
                ),
    'user': (
            ['--user'],
            {'metavar': 'USERNAME',
             'default': None,
             'type': str,
             'help': "The user for an anvi'server."}
                ),
    'read-only': (
            ['--read-only'],
            {'default': False,
             'action': 'store_true',
             'help': "When the interactive interface is started with this flag, all 'database write'\
                      operations will be disabled."}
                ),
    'server-only': (
            ['--server-only'],
            {'default': False,
             'action': 'store_true',
             'help': "The default behavior is to start the local server, and fire up a browser that\
                      connects to the server. If you have other plans, and want to start the server\
                      without calling the browser, this is the flag you need."}
                ),
    'skip-store-in-db': (
            ['--skip-store-in-db'],
            {'default': False,
             'action': 'store_true',
             'help': "By default, analysis results are stored in the profile database. The use of\
                      this flag will let you skip that"}
                ),
    'min-e-value': (
            ['-e', '--min-e-value'],
            {'metavar': 'E-VALUE',
             'default': 1e-15,
             'type': float,
             'help': "Minimum significance score of an HMM find to be considered as a valid hit.\
                      Default is %(default)g."}
                ),
    'min-percent-identity': (
            ['--min-percent-identity'],
            {'metavar': 'PERCENT_IDENTITY',
             'default': 80.0,
             'type': float,
             'help': "Minimum percent identity. The default is %(default)g."}
                ),
    'bins-info': (
            ['--bins-info'],
            {'metavar': 'BINS_INFO',
             'help': "Additional information for bins. The file must contain three TAB-delimited columns,\
                      where the first one must be a unique bin name, the second should be a 'source', and the\
                      last one should be a 7 character HTML color code (i.e., '#424242'). Source column must\
                      contain information about the origin of the bin. If these bins are automatically\
                      identified by a program like CONCOCT, this column could contain the program name and\
                      version. The source information will be associated with the bin in various interfaces\
                      so in a sense it is not *that* critical what it says there, but on the other hand it is,\
                      becuse we should also think about people who may end up having to work with what we put\
                      together later."}
                ),
    'bins': (
            ['--bins'],
            {'metavar': 'BINS_DATA',
             'help': "Tab-delimited file, first column contains tree leaves (protein clusters, splits, contigs etc.) \
                      and second column contains which Bin they belong."
            }
      ),
    'contigs-mode': (
            ['--contigs-mode'],
            {'default': False,
             'action': 'store_true',
             'help': "Use this flag if your binning was done on contigs instead of splits. Please refer\
                      to the documentation for help."}
                ),
    'sample-name': (
            ['-S', '--sample-name'],
            {'metavar': 'NAME',
             'help': "It is important to set a sample name (using only ASCII letters and digits\
                      and without spaces) that is unique (considering all others). If you do not\
                      provide one, anvi'o will try to make up one for you based on other information,\
                      although, you should never let the software to decide these things)."}
                ),
    'project-name': (
            ['-n', '--project-name'],
            {'metavar': 'PROJECT_NAME',
             'help': "Name of the project. Please choose a short but descriptive name (so anvi'o can use\
                      it whenever she needs to name an output file, or add a new table in a database, or name\
                      her first born)."}
                ),
    'skip-hierarchical-clustering': (
            ['--skip-hierarchical-clustering'],
            {'default': False,
             'action': 'store_true',
             'help': "If you are not planning to use the interactive interface (or if you have other\
                      means to add a tree of contigs in the database) you may skip the clustering step\
                      and simply just merge multiple runs."}
                ),
    'enforce-hierarchical-clustering': (
            ['--enforce-hierarchical-clustering'],
            {'default': False,
             'action': 'store_true',
             'help': "If you have more than 25,000 splits in your merged profile, anvi-merge will automatically\
                      skip the hierarchical clustering of splits (by setting --skip-hierarchical-clustering flag\
                      on). This is due to the fact that computational time required for hierarchical clustering\
                      increases exponentially with the number of items being clustered. Based on our experience\
                      we decided that 25,000 splits is about the maximum we should try. However, this is not a\
                      theoretical limit, and you can overwrite this heuristic by using this flag, which would\
                      tell anvi'o to attempt to cluster splits regardless."}
                ),
    'compress-auxiliary-data': (
            ['--compress-auxiliary-data'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the auxiliary data file in the resulting output will be compressed. This\
                      saves space, but it takes long. Also, if you are planning to compress the entire\
                      later using GZIP, it is even useless to do. But you are the boss!"}
                ),
    'cluster-contigs': (
            ['--cluster-contigs'],
            {'default': False,
             'action': 'store_true',
             'help': "Single profiles are rarely used for genome binning or visualization, and since\
                      clustering step increases the profiling runtime for no good reason, the default\
                      behavior is to not cluster contigs for individual runs. However, if you are\
                      planning to do binning on one sample, you must use this flag to tell anvio to\
                      run cluster configurations for single runs on your sample."}
                ),
    'skip-concoct-binning': (
            ['--skip-concoct-binning'],
            {'default': False,
             'action': 'store_true',
             'help': "Anvi'o uses CONCOCT (Alneberg et al.) by default for unsupervised genome binning\
                      for merged runs. CONCOCT results are stored in the profile database, which then\
                      can be used from within appropriate interfaces (i.e., anvi-interactive, anvi-summary,\
                      etc). Use this flag if you would like to skip this step"}
                ),
    'num-clusters-requested': (
            ['--num-clusters-requested'],
            {'metavar': 'INT',
             'default': 400,
             'type': int,
             'help': "How many clusters do you request? Default is %(default)d."}
             ),
    'overwrite-output-destinations': (
            ['-W', '--overwrite-output-destinations'],
            {'default': False,
             'action': 'store_true',
             'help': "Overwrite if the output files and/or directories exist."}
                ),
    'delete-if-exists': (
            ['--delete-if-exists'],
            {'default': False,
             'action': 'store_true',
             'help': "Be bold (at your own risk), and delete if exists."}
                ),
    'report-variability-full': (
            ['--report-variability-full'],
            {'default': False,
             'action': 'store_true',
             'help': "One of the things anvi-profile does is to store information about variable\
                      nucleotide positions. Usually it does not report every variable position, since\
                      not every variable position is geniune variation. Say, if you have 1,000 coverage,\
                      and all nucleotides at that position are Ts and only one of them is a C, the\
                      confidence of that C being a real variation is quite low. anvio has a simple\
                      algorithm in place to reduce the impact of noise. However, using this flag\
                      you can diable it and ask profiler to report every single variation (which\
                      may result in very large output files and millions of reports, but you are the\
                      boss). Do not forget to take a look at '--min-coverage-for-variability' parameter"}
                ),
    'report-extended-deflines': (
            ['--report-extended-deflines'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the deflines in the resulting FASTA file will contain more information."}
                ),
    'manual-mode': (
            ['--manual-mode'],
            {'default': False,
             'action': 'store_true',
             'help': "Using this flag, you can run the interactive interface in an ad hoc manner using\
                      input files you curated instead of standard output files generated by an anvi'o\
                      run. In the manual mode you will be asked to provide a profile database. In this\
                      mode a profile database is only used to store 'state' of the interactive interface\
                      so you can reload your visual settings when you re-analyze the same files again. If\
                      the profile database you provide does not exist, anvi'o will create an empty one for\
                      you."}
                ),
    'hmm-profile-dir': (
            ['-H', '--hmm-profile-dir'],
            {'metavar': 'HMM PROFILE PATH',
             'help': "You can use this parameter you can specify a directory path that contain an HMM profile.\
                      This way you can run HMM profiles that are not included in anvi'o. See the online\
                      to find out about the specifics of this directory structure ."}
                ),
    'installed-hmm-profile': (
            ['-I', '--installed-hmm-profile'],
            {'metavar': 'HMM PROFILE NAME'}
                ),
    'min-contig-length': (
            ['-M', '--min-contig-length'],
            {'metavar': 'INT',
             'default': 2500,
             'type': int,
             'help': "Minimum length of contigs in a BAM file to analyze. The minimum length should be long enough\
                      for tetra-nucleotide frequency analysis to be meaningful. There is no way to define a golden\
                      number of minumum length that would be applicable to genomes found in all environments, but we\
                      chose the default to be %(default)d, and have been happy with it. You are welcome to experiment,\
                      but we advise to never go below 1,000. You also should remember that the lower you go, the more\
                      time it will take to analyze all contigs. You can use --list-contigs parameter to have an idea how\
                      many contigs would be discarded for a given M."}
                ),
    'min-mean-coverage': (
            ['-X', '--min-mean-coverage'],
            {'metavar': 'INT',
             'default': 0,
             'type': int,
             'help': "Minimum mean coverage for contigs to be kept in the analysis. The default value is %(default)d,\
                      which is for your best interest if you are going to profile muptiple BAM files which are then\
                      going to be merged for a cross-sectional or time series analysis. Do not change it if you are not\
                      sure this is what you want to do."}
                ),
    'min-coverage-for-variability': (
            ['-V', '--min-coverage-for-variability'],
            {'metavar': 'INT',
             'default': 10,
             'type': int,
             'help': "Minimum coverage of a nucleotide position to be subjected to SNV profiling. By default, anvio will\
                      not attempt to make sense of variation in a given nucleotide position if it is covered less than\
                      %(default)dX. You can change that minimum using this parameter."}
                ),
    'contigs-and-positions': (
            ['--contigs-and-positions'],
            {'metavar': 'CONTIGS_AND_POS',
             'required': True,
             'help': "This is the file where you list the contigs, and nucleotide positions you are interested in. This\
                      is supposed to be a TAB-delimited file with two columns. In each line, the first column should be\
                      the contig name, and the second column should be the comma-separated list of integers for nucleotide\
                      positions."}
                ),
    'state-autoload': (
            ['--state-autoload'],
            {'metavar': 'NAME',
             'help': "Automatically load previous saved state and draw tree. To see a list of available states,\
                      use --show-states flag."}
                ),
    'state': (
            ['-s', '--state'],
            {'metavar': 'STATE',
             'help': "State file, you can export states from database using anvi-export-state program"}
                ),
    'collection-autoload': (
            ['--collection-autoload'],
            {'metavar': 'NAME',
             'help': "Automatically load a collection and draw tree. To see a list of available collections,\
                      use --list-collections flag."}
                ),
    'full-report': (
            ['--full-report'],
            {'metavar': 'FILE_NAME',
             'default': None,
             'help': "Optional output file with a fuller description of findings."}
                ),
    'show-states': (
            ['--show-states'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared the program will print all available states and exit."}
                ),
    'skip-init-functions': (
            ['--skip-init-functions'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, function calls for genes will not be initialized (therefore will be missing from all\
                      relevant interfaces or output files). The use of this flag may reduce the memory fingerprint and\
                      processing time for large datasets."}
                ),
    'init-gene-coverages': (
            ['--init-gene-coverages'],
            {'default': False,
             'action': 'store_true',
             'help': "Initialize gene coverage and detection data. This is a very computationally expensive step, but it is\
                      necessary when you need gene level coverage data. The reason this is very computationally expensive\
                      is because anvi'o computes gene coverages by going back to actual coverage values of each gene to\
                      average them, instead of using contig average coverage values, for extreme accuracy."}
                ),
    'skip-auto-ordering': (
            ['--skip-auto-ordering'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, the attempt to include automatically generated orders of items based on additional data\
                      is skipped. In case those buggers cause issues with your data, and you still want to see your stuff and\
                      deal with the other issue maybe later."}
                ),
    'quick-summary': (
            ['--quick-summary'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared the summary output will be generated as quickly as possible, with minimum amount\
                      of essential information about bins."}
                ),
    'only-complete-links': (
            ['--only-complete-links'],
            {'default': False,
             'action': 'store_true',
             'help': "When declared, only reads that cover all positions will be reported. It is necessary to use this\
                      flag if you want to perform oligotyping-like analyses on matching reads."}
                ),
    'users-data-dir': (
            ['-U', '--users-data-dir'],
            {'metavar': 'USERS_DATA_DIR',
             'type': str,
             'help': "Input directory where the user database is read and stored by the server. A new database will be\
                      created if no directory is found."}
                ),
    'smtp-config-file': (
            ['-E', '--smtp-config-file'],
            {'metavar': 'SMTP_CONFIG_INI',
             'type': str,
             'help': "The configuration file for SMTP server to send e-mails. The input file should be formatted as an INI\
                      file that starts with the header '[SMTP]', and should describe values of each of these variables in\
                      the following lines: 'from_address' (the e-mail address that should appear in the 'From' section of\
                      e-mails sent by the server), 'server_address' (the address of the SMTP server to connect), 'server_port'\
                      (the port number to connect), 'init_tls' (whether to initialize TLS protocol), 'username' (the username\
                      for the server to login, if necessary), 'password' (the password associated with the username for login,\
                      if the password is not blank)."}
                ),
    'validate-users-automatically': (
            ['--validate-users-automatically'],
            {'default': True,
             'action': 'store_true',
             'help': "If this is true, users will not receive a link via email to confirm their account but instead be validated\
                      automatically if there is no smtp configuration."}
                ),
    'queue-size': (
            ['--queue-size'],
            {'default': 0,
             'metavar': 'INT',
             'required': False,
             'help': "The queue size for worker threads to store data to communicate to the main thread. The default is set by the\
                      class based on the number of threads. If you have *any* hesitation about whther you know what you are doing,\
                      you should not change this value."}
                ),
    'write-buffer-size': (
            ['--write-buffer-size'],
            {'default': 500,
             'metavar': 'INT',
             'required': False,
             'help': "How many items should be kept in memory before they are written do the disk. The default is %(default)d.\
                      The larger the buffer size, the less frequent the program will access to the disk, yet the more memory\
                      will be consumed since the processed items will be cleared off the memory only after they are written\
                      to the disk. The default buffer size will likely work for most cases, but if you have very large\
                      contigs, you may need to decrease this value. Please keep an eye on the memory usage output to make sure\
                      the memory use never exceeds the size of the physical memory."}
                ),
    'export-gff3': (
        ['--export-gff3'],
        {
            'default': False,
            'action': 'store_true',
            'help': "If this is true, the output file will be in GFF3 format."
        }
    ),
    'export-svg': (
            ['--export-svg'],
            {'type': str,
             'metavar': 'FILE_PATH',
             'required': False,
             'help': "The SVG output file path."}
                ),
    'tab-delimited': (
            ['--tab-delimited'],
            {'default': False,
             'required': False,
             'action': 'store_true',
             'help': "Use the TAB-delimited format for the output file."}
                ),
    'splits-mode': (
            ['--splits-mode'],
            {'default': False,
             'action': 'store_true',
             'help': "Specify this flag if you would like to output coverages of individual 'splits', rather than their 'parent'\
                      contig coverages."}
                ),
}

# two functions that works with the dictionary above.
def A(param_id):
    return D[param_id][0]

def K(param_id, params_dict={}):
    kwargs = copy.deepcopy(D[param_id][1])
    for key in params_dict:
        kwargs[key] = params_dict[key]

    return kwargs


# The rest of this file is composed of code that responds to '-v' or '--version' calls from clients,
# and provides access to the database version numbers for all anvi'o modules.

import anvio.tables as t
from anvio.terminal import Run


run = Run()


def set_version():
    anvio_version = 'unknown'

    try:
        anvio_version = pkg_resources.require("anvio")[0].version
    except:
        # maybe anvi'o is not installed but it is being run from the codebase dir?
        # some hacky stuff to get version from the setup.py
        try:
            setup_py_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__))) + '/../setup.py'
            version_string = [l.strip() for l in open(setup_py_path).readlines() if l.strip().startswith('anvio_version')][0]
            anvio_version = version_string.split('=')[1].strip().strip("'").strip('"')
        except:
            pass

    return anvio_version, \
           t.contigs_db_version, \
           t.pan_db_version, \
           t.profile_db_version, \
           t.samples_info_db_version, \
           t.auxiliary_hdf5_db_version, \
           t.genomes_storage_hdf5_db_vesion, \
           t.users_db_version


def print_version():
    run.info("Anvi'o version", __version__, mc='green')
    run.info("Profile DB version", __profile__version__)
    run.info("Contigs DB version", __contigs__version__)
    run.info("Pan DB version", __pan__version__)
    run.info("Samples information DB version", __samples__version__)
    run.info("Genome data storage version", __hdf5__version__)
    run.info("Auxiliary data storage version", __genomes_storage_version__)
    run.info("Anvi'server users data storage version", __users_db_version__)


__version__, \
__contigs__version__, \
__pan__version__, \
__profile__version__, \
__samples__version__, \
__hdf5__version__, \
__genomes_storage_version__, \
__users_db_version__ = set_version()


if '-v' in sys.argv or '--version' in sys.argv:
    print_version()
    sys.exit()
