from collections import OrderedDict

from multiqc.utils import config

from .plot_basic_hist import plot_basic_hist
from .plot_aqhist import plot_aqhist
from .plot_bhist import plot_bhist
from .plot_bqhist import plot_bqhist
from .plot_covhist import plot_covhist
from .plot_idhist import plot_idhist
from .plot_ihist import plot_ihist
from .plot_indelhist import plot_indelhist
from .plot_mhist import plot_mhist
from .plot_qahist import plot_qahist
from .plot_qhist import plot_qhist

class slice2OrderedDict(object):
    def __getitem__(self, keys):
        return OrderedDict([(slice.start, slice.stop) for slice in keys])
odict = slice2OrderedDict()

section_order = [
    'stats',
    'covhist',
    'covstats',
    'bincov',
    'bqhist',
    'idhist',
    'indelhist',
    'mhist',
    'qahist',
    'qhist',
    'aqhist',
    'ehist',
    'lhist',
    'ihist',
    'gchist',
    'bhist' ,

    'rpkm',
    'statsfile_machine',
    'statsfile',
]
file_types = {
    'stats': {
        'title': 'BBDuk filtering statistics',
        'descr': 'Proportion of reads that matched adapters/contaminants.',
        'help_text': '',
        'kvrows': ['Total', 'Matched'],
        'kv_descriptions': {
            'Total': (
                'Total number of reads processed',
                {
                    'description': 'Aligned Reads ({})'.format(config.read_count_desc),
                    'shared_key': 'read_count',
                    'modify': lambda x: x * config.read_count_multiplier,
                    'scale': 'PuBu',
                    'hidden': True
                }
            ),
            'Matched': (
                'Total number of reads matching adapters/contaminants',
                {
                    'description': 'Aligned Reads ({})'.format(config.read_count_desc),
                    'shared_key': 'read_count',
                    'modify': lambda x: x * config.read_count_multiplier,
                    'scale': 'Reds',
                    'hidden': True
                }
            ),
            'Percent filtered': (
                'Proportion of reads filtered, matching adapters/contaminants',
                {
                    'max': 100,
                    'min': 0,
                    'scale': 'OrRd',
                    'suffix': '%',
                    'hidden': False
                }
            ),
        },
        'cols': odict[
            'Name':str,
            'Reads':int,
            'ReadsPct':lambda v: float(v.strip("%"))],
        'plot_func': None,  ## Plotting for 'stats' not implemented
        'plot_params': {},
    },
    'aqhist': {
        'title': 'Read quality',
        'descr': 'Histogram of average read qualities (`aqhist`). '
                 'Plot shows the number of reads at each quality score.',
        'help_text': '',
        'cols': odict[
            'Quality':int,
            'count1':int,
            'fraction1':float,
            'count2':int,
            'fraction2':float
        ],
        'plot_func': plot_aqhist,
        'plot_params': {
            'xPlotBands':
            [
                {'from': 28, 'to': 100, 'color': '#c3e6c3'},
                {'from': 20, 'to': 28, 'color': '#e6dcc3'},
                {'from': 0, 'to': 20, 'color': '#e6c3c3'},
            ],
            'yLog': True,
        }
    },
#basecov
#  - Coverage per base location.
#  - too big to interpret here
    'bhist' : {
        'title': 'Base composition',
        'descr': 'Base composition histogram by position (`bhist`). '
                 'The plot shows the percentage of `G+C`, `A+T`, and `N` bases '
                 'for each position in the reads.',
        'help_text': 'Relative composition',
        'cols': odict[
            'Pos':int, 'A':float, 'C':float, 'G':float, 'T':float, 'N':float
        ],
        'plot_func': plot_bhist,
        'plot_params': {},
    },
    'bincov': {
        'title': 'Binned coverage',
        'descr': 'Binned coverage per location, one line per X bases (`bincov`).',
        'help_text': '',
        'kvrows': ['Mean', 'STDev' ],
        'cols': odict[
            'RefName':str,
            'Cov':float,
            'Pos':int,
            'RunningPos':int
        ],
        'plot_func': plot_basic_hist,
        'plot_params': {},
        'not_implemented': ''
    },
    'bqhist': {
        'title': 'Base quality',
        'descr': 'Quality histogram designed for box plots (`bqhist`). '
                 'Refer to original source files for complete boxplot data. '
                 'Plot shows mean base quality for each read position. ',
        'help_text': '',
        'cols': odict[
            'BaseNum':int,
            'count_1':int, 'min_1':int, 'max_1':int, 'mean_1':float,
            'Q1_1':int, 'med_1':int, 'Q3_1':int, 'LW_1':int, 'RW_1':int,
            'count_2':int, 'min_2':int, 'max_2':int, 'mean_2':float,
            'Q1_2':int, 'med_2':int, 'Q3_2':int, 'LW_2':int, 'RW_2':int
        ],
        'plot_func': plot_bqhist,
        'plot_params': {}
    },
    'covhist': {
        'title': 'Coverage histogram',
        'descr': 'Histogram of number of occurrences of each coverage depth level (`covhist`). '
                 'Note that lines have been smoothed to 400 points; '
                 'higher resolution data might be available in the original data source. ',
        'help_text': '',
        'cols': odict['Coverage':int, 'numBases':int],
        'plot_func': plot_covhist,
        'plot_params': {
            'yLog': True,
        }
    },
    'covstats': {
        'title': 'Coverage stats',
        'descr': 'Per-scaffold coverage info (`covstats`).',
        'help_text': '',
        'cols': odict[
            'ID':str,
            'Avg_fold':float
        ],
        'extracols': odict[
            'Length':int,
            'Ref_GC':float,
            'Covered_percent':float,
            'Covered_bases':int,
            'Plus_reads':int,
            'Minus_reads':int,
            'Median_fold':int,
            'Read_GC':float,
            'Std_Dev':float
        ],
        'plot_func': plot_basic_hist,
        'plot_params': {},
        'not_implemented': ''
    },
    'ehist': {
        'title': 'Errors-per-read',
        'descr': 'Errors-per-read histogram (`ehist`). ',
        'help_text': '',
        'cols': odict['Errors':int, 'Count':int ],
        'plot_func': plot_basic_hist,
        'plot_params': {
            'xlab': 'Errors',
            'ylab': '# Reads'
        }
    },
    'gchist' : {
        'title': 'GC content',
        'descr': 'Read GC content histogram (`gchist`).',
        'help_text': '',
        'kvrows': ['Mean', 'Median', 'Mode', 'STDev'],
        'kv_descriptions': {
            'Mean': ('Average GC content', {}),
            'Median': ('Median GC content', {}),
            'Mode': ('The most commonly occuring value of the GC content distribution', {}),
            'STDev': ('Standard deviation of average GC content', {}),
        },
        'cols': odict['GC':float, 'Count':int ],
        'plot_func': plot_basic_hist,
        'plot_params': {
            'xlab': 'Proportion GC',
            'ylab': '# Reads'
        }
    },
    'idhist': {
        'title': 'Identity histogram',
        'descr': 'Histogram of read count versus percent base pair identity '
                 'of aligned reads (`idhist`).',
        'help_text': '',
        'kvrows': ['Mean_reads', 'Mean_bases',
                   'Median_reads', 'Median_bases',
                   'Mode_reads', 'Mode_bases',
                   'STDev_reads', 'STDev_bases' ],
        'kv_descriptions': {
            'Mean_reads': ('Average percent identity of aligned reads', {}),
            'Mean_bases': ('Average percent identity of aligned bases', {}),
            'Median_reads': ('Median percent identity of aligned reads', {}),
            'Median_bases': ('Median percent identity of aligned bases', {}),
            'Mode_reads': ('The most commonly occuring average value amongst aligned reads (i.e. the mode of the distribution)', {}),
            'Mode_bases': ('The most commonly occuring average value amongst aligned bases (i.e. the mode of the distribution)', {}),
            'STDev_reads': ('The standard deviation of the average percent identity distribution for aligned reads', {}),
            'STDev_bases': ('The standard deviation of the average percent identity distribution for aligned bases', {}),
        },
        'cols': odict[
            'Identity':float, 'Reads':int, 'Bases':int
        ],
        'plot_func': plot_idhist,
        'plot_params': {}
    },
    'ihist': {
        'title': 'Insert sizes',
        'descr': 'Histogram of computed insert sizes, for paired reads (`ihist`). '
                 'Plotted data has been cut off at 99% to prevent long tails; '
                 'Complete data available in original source files.',
        'help_text': 'The insert size is the length of the sequence between the '
                     'sequencing adapters, which for most common insert sizes is '
                     'longer than the sum of both read pairs. '
                     'In some cases, the insert size is shorter than the length '
                     'of the two read pairs combined, resulting in an insert size '
                     'shorter than the sum of the length of the reads pairs.',
        'kvrows': ['Mean', 'Median', 'STDev', 'PercentOfPairs'],
        'kv_descriptions': {
            'Mean': ('Average insert length', {}),
            'Median': ('Median insert length', {}),
            'STDev': ('Standard deviation of insert size length distribution', {}),
            'PercentOfPairs': ('', {}),
        },
        'cols': odict['InsertSize':int, 'Count':int ],
        'plot_func': plot_ihist,
        'plot_params': {}
    },
    'indelhist': {
        'title': 'Indel lengths',
        'descr': 'Indel length histogram (`indelhist`). '
                 'The plots show the number of observed insertions and deletions, '
                 'for each insertion and deletion length.',
        'help_text': '',
        'cols': odict['Length':int, 'Deletions':int, 'Insertions':int],
        'plot_func': plot_indelhist,
        'plot_params': {}
    },
    'lhist' : {
        'title': 'Read lengths',
        'descr': 'Read length histogram (`lhist`).',
        'help_text': '',
        'cols': odict['Length':int, 'Count':int ],
        'plot_func': plot_basic_hist,
        'plot_params': {
            'xlab': 'Read length (base pairs)',
            'ylab': '# Reads'
        }
    },
    'mhist': {
        'title': 'Match, substitution, deletion, and insertion rates',
        'descr': 'Histogram of match, substitution, deleletion, '
                 'and insertion rates by read location (`mhist`).',
        'help_text': '',
        'cols': odict[
            'BaseNum':int,
            'Match1':float, 'Sub1':float, 'Del1':float, 'Ins1':float, 'N1':float, 'Other1':float,
            'Match2':float, 'Sub2':float, 'Del2':float, 'Ins2':float, 'N2':float, 'Other2':float
        ],
        'plot_func': plot_mhist,
        'plot_params': {}
    },
    'qahist': {
        'title': 'Quality accuracy',
        'descr': 'Base quality accuracy histogram of error rates versus quality score (`qahist`). '
                 'The plots show the observed count of each type of alignment by base quality score.',
        'help_text': '',
        'kvrows': ['Deviation', 'DeviationSub' ],
        'kv_descriptions': {
            'Deviation': ('', {}),
            'DeviationSub': ('', {}),
        },
        'cols': odict[
            'Quality':int, 'Match':int, 'Sub':int, 'Ins':int, 'Del':int,
            'TrueQuality':float, 'TrueQualitySub':float
        ],
        'plot_func': plot_qahist,
        'plot_params': {}
    },
    'qhist': {
        'title': 'Sequence Quality Histograms',
        'descr': 'Quality histogram by position (`qhist`). '
                 'The plots show the average quality for each position in the reads, '
                 'using the linear values, logarithmically scaled values, and the '
                 'actual measured qualities based on the alignments.',
        'help_text': '',
        'cols': odict[
            'BaseNum':int,
            'Read1_linear':float,
            'Read1_log':float,
            'Read1_measured':float,
            'Read2_linear':float,
            'Read2_log':float,
            'Read2_measured':float
        ],
        'plot_func': plot_qhist,
        'plot_params': {}
    },
    'rpkm': {
        'title': 'RPKM/FPKM',
        'descr': 'Per-scaffold RPKM/FPKM counts (`rpkm`).',
        'help_text': '',
        'kvrows': ['File', 'Reads', 'Mapped', 'RefSequences' ],
        'kv_descriptions': {
            'File': ('', {}),
            'Reads': ('', {}),
            'Mapped': ('', {}),
            'RefSequences': ('', {}),
        },
        'cols': odict[
            'Name':str,
            'Length':int, 'Bases':int, 'Coverage':float,
            'Reads':int, 'RPKM':float, 'Frags':int, 'FPKM':float
        ],
        'plot_func': plot_basic_hist,
        'plot_params': {},
        'not_implemented': '',
    },
    'statsfile_machine': {
        'title': 'General stats',
        'descr': 'General Stats (`statsfile_machine`).',
        'help_text': '',
        'cols': [],
        'plot_func': plot_basic_hist,
        'plot_params': {}
    },
    'statsfile': {
        'title': 'General stats',
        'descr': 'General Stats (`statsfile`).',
        'help_text': '',
        'cols': [],
        'plot_params': {},
        'plot_func': plot_basic_hist,
        'not_implemented': ''
    }
}

statsfile_machine_keys = [
    'Reads_Used', 'Bases_Used', 'Reads/sec', 'kBases/sec',

    'R1_Mapped_Percent', 'R1_Unambiguous_Percent', 'R1_Mapped_Reads',
    'R1_Unambiguous_Reads', 'Mated_Pairs', 'Bad_Pairs', 'R1_Rescued',
    'Avg_Insert_Size', 'R1_Perfect_Best_Site', 'R1_Semiperfect_Site',
    'R1_Ambiguous_Mapping', 'R1_Low_Quality_Discards', 'R1_Match_Rate',
    'R1_Error_Rate', 'R1_Sub_Rate', 'R1_Del_Rate', 'R1_Ins_Rate',
    'R1_N_Rate', 'R1_Match_Count', 'R1_Error_Count', 'R1_Sub_Count',
    'R1_Del_Count', 'R1_Ins_Count', 'R1_N_Count',

    'R2_Mapped_Percent', 'R2_Unambiguous_Percent', 'R2_Mapped_Reads',
    'R2_Unambiguous_Reads', 'R2_Rescued', 'R2_Perfect_Best_Site',
    'R2_Semiperfect_Site', 'R2_Ambiguous_Mapping', 'R2_Low_Quality_Discards',
    'R2_Match_Rate', 'R2_Error_Rate', 'R2_Sub_Rate', 'R2_Del_Rate',
    'R2_Ins_Rate', 'R2_N_Rate', 'R2_Match_Count', 'R2_Error_Count',
    'R2_Sub_Count', 'R2_Del_Count', 'R2_Ins_Count', 'R2_N_Count',
    'R2_Mapped_Percent',

]
