#!/usr/bin/env python
# encoding: utf-8
'''
dps.analysis.xsection.05b_make_tables -- creates tables for documentation

dps.analysis.xsection.05b_make_tables is a script to create 


@copyright:  2015 University of Bristol. All rights reserved.

@license:    Apache License 2.0

@contact:    L.Kreczko@bristol.ac.uk
@deffield    updated: 27.07.2015
'''

import sys
import os

from optparse import OptionParser
from dps.config.xsection import XSectionConfig
from dps.utils.table import PrintTable
from dps.analysis.xsection.lib import read_initial_normalisation,\
    read_unfolded_normalisation
from dps.config.variable_binning import variable_bins_latex, variable_bins_visiblePS_latex

from dps.utils.logger import log
from math import ceil
mylog = log["05_make_tables"]

__all__ = []
__version__ = 0.1
__date__ = '2015-07-27'
__updated__ = '2015-08-20'

DEBUG = 0
TESTRUN = 0
PROFILE = 1


@mylog.trace()
def main(argv=None):
    '''Command line options.'''

    program_name = os.path.basename(sys.argv[0])
    program_version = "v0.1"
    program_build_date = "%s" % __updated__

    program_version_string = '%%prog %s (%s)' % (
        program_version, program_build_date)
    # program_usage = '''usage: spam two eggs''' # optional - will be
    # autogenerated by optparse
    program_longdesc = ''''''  # optional - give further explanation about what the program does
    program_license = "Copyright 2015 user_name (organization_name)                                            \
                Licensed under the Apache License 2.0\nhttp://www.apache.org/licenses/LICENSE-2.0"

    if argv is None:
        argv = sys.argv[1:]
    # setup option parser
    parser = OptionParser(
        version=program_version_string, epilog=program_longdesc, description=program_license)
    parser.add_option(
        "-i", "--in", dest="input_path", help="set input path [default: %default]")
    parser.add_option(
        "-o", "--out", dest="output_path", help="set output path [default: %default]")
    parser.add_option("-v", "--variable", dest="variable",
                      help="set the variable to analyse (MET, HT, ST, MT, WPT) [default: %default]")
    parser.add_option("-c", "--centre-of-mass-energy", dest="com", type=int,
                      help="set the centre of mass energy in TeV for analysis. [default: %default]")
    parser.add_option('--visiblePS', dest="visiblePS", action="store_true",
                      help="Unfold to visible phase space")

    # set defaults
    parser.set_defaults(
        output_path="tables/background_subtraction/",
        input_path="data/normalisation/background_subtraction/",
        com=13,
        variable='MET',
    )

    # process options
    (opts, _) = parser.parse_args(argv)

    # MAIN BODY #
    config = XSectionConfig(opts.com)
    met_type = config.translate_options['type1']
    variable = opts.variable
    output_path = opts.output_path
    input_path = opts.input_path
    visiblePS = opts.visiblePS

    if not output_path.endswith('/'):
        output_path += '/'

    phase_space = 'FullPS'
    if visiblePS:
        phase_space = 'VisiblePS'

    path_to_JSON = '{path}/{com}TeV/{variable}/{phase_space}/'.format(
        path=input_path,
        com=opts.com,
        variable=variable,
        phase_space=phase_space,
    )
#         categories_and_prefixes = config.categories_and_prefixes
#         categories = deepcopy(categories_and_prefixes.keys())

    for channel in ['electron', 'muon']:  # , 'combined']:
        # read results
        unfolded_normalisation = read_unfolded_normalisation(
            path_to_JSON=path_to_JSON,
            category='central',
            channel=channel,
            met_type=met_type,
        )
        initial_normalisation = read_initial_normalisation(
            path_to_JSON=path_to_JSON,
            category='central',
            channel=channel,
            met_type=met_type,
        )
        mylog.debug('initial normalisation entries: ')
        mylog.debug(initial_normalisation.keys())
        mylog.debug('unfolded normalisation entries: ')
        mylog.debug(unfolded_normalisation.keys())

        print_result_table(
            config,
            channel, opts, initial_normalisation, unfolded_normalisation,
        )


@mylog.trace()
def print_result_table(
        config, channel, options,
        initial_normalisation, unfolded_normalisation):

    print_xsection_table(
        config, channel, options,
        initial_normalisation, unfolded_normalisation,
    )
    print_normalisation_table(
        config, channel, options,
        initial_normalisation, unfolded_normalisation,
    )


@mylog.trace()
def print_xsection_table(config, channel, options, initial_normalisation,
                         unfolded_normalisation):
    pass


@mylog.trace()
def print_normalisation_table(config, channel, options, initial_normalisation,
                              unfolded_normalisation):
    cols = 0
    variable = options.variable
    # construct header
    data = []
    n_data = ['data']
    n_data.extend([int(v) for (v, _) in initial_normalisation['data']])
    data.append(n_data)
    for sample in config.samples:
        if sample == 'TTJet':
            continue
        values = initial_normalisation[sample]
        values = [process_values(v) for v in values]

        cols = len(values) + 1
        row = [sample]
        row.extend(values)
        data.append(row)
    data.append([''] * cols)

    headers = [variable]
    bins = variable_bins_latex[variable]
    if options.visiblePS:
        bins = variable_bins_visiblePS_latex[variable]
    headers.extend(bins.itervalues())  # replace with bins

    measured = ['\\ttbar event yield']
    measured.extend([process_values(v)
                     for v in unfolded_normalisation['TTJet_measured']])
    mc_pred = ['MC prediction']
    mc_pred.extend([process_values(v)
                    for v in initial_normalisation['TTJet']])

    data.append(measured)
    data.append(mc_pred)
    data.append([''] * cols)

    unfolded = ['\\ttbar event yield']
    unfolded.extend([process_values(v)
                     for v in unfolded_normalisation['TTJet_unfolded']])
    mc_pred = ['MC prediction']
    mc_pred.extend([process_values(v)
                    for v in unfolded_normalisation['POWHEG_HERWIG']])
    data.append(unfolded)
    data.append(mc_pred)

    table = PrintTable(data, headers)
    print table.latex()


@mylog.trace()
def print_systematics(channel, options):
    pass


def process_values(values):
    value, error = values
    value = int(round(value, 0))
    error = int(ceil(error))
    return '{0} +- {1}'.format(value, error)

if __name__ == "__main__":
    if DEBUG:
        log.setLevel(log.DEBUG)
    if TESTRUN:
        import doctest
        doctest.testmod()
    if PROFILE:
        import cProfile
        import pstats
        profile_filename = 'dps.analysis.xsection.05b_make_tables_profile.txt'
        cProfile.run('main()', profile_filename)
        statsfile = open("profile_stats.txt", "wb")
        p = pstats.Stats(profile_filename, stream=statsfile)
        stats = p.strip_dirs().sort_stats('cumulative')
        stats.print_stats()
        statsfile.close()
        sys.exit(0)
    sys.exit(main())
