# coding: utf-8
from .const import CLI_REPORTS, ARGS_FILE_PATH
from os.path import dirname, join
import json
import yaml


def return_possible_sheets(for_reports):
    possible_sheets = [config["meta"]["sheet_names"] for report, config in CLI_REPORTS_CONFIG.iteritems()
                       if report in for_reports]
    possible_sheets = sum(possible_sheets, [])
    possible_sheets = [sheet_name for i, sheet_name in enumerate(possible_sheets)
                       if sheet_name not in possible_sheets[:i]]
    return possible_sheets


def return_possible_presets(for_reports):
    possible_presets = [config["meta"]["presets"] for report, config in CLI_REPORTS_CONFIG.iteritems()
                        if report in for_reports]
    possible_presets = list(set(sum(possible_presets, [])))
    return possible_presets


def return_reports(selected_sheets=None, selected_presets=None, selected_reports=None):
    """
    Если на входе список листов, то функция возвращает список отчетов, в которые они входят.
    Если список пресетов - то список листов и отчетов.
    Если и листы, и пресеты == None, возвращается список всех возможных листов.
    """

    reports = []
    if not selected_reports:
        selected_reports = CLI_REPORTS
    possible_sheets = return_possible_sheets(selected_reports)
    if selected_sheets:
        for sheet_name in selected_sheets:
            if sheet_name not in possible_sheets:
                raise KeyError("unknown sheet `%s`" % sheet_name)

        # Поиск отчетов, в которые входят выбранные листы
        for report, config in CLI_REPORTS_CONFIG.iteritems():
            if filter(lambda sheet_name: sheet_name in config["meta"]["sheet_names"], selected_sheets):
                reports.append(report)

        return reports

    if selected_presets:

        selected_sheets = []

        possible_presets = return_possible_presets(selected_reports)
        for preset in selected_presets:
            if preset not in possible_presets:
                raise KeyError("unknown preset `%s`. Valid presets: %s." % (preset, ", ".join(possible_presets)))

        # Поиск отчетов, которые входят в пресеты + поиск листов выбранных пресетов
        for report, config in CLI_REPORTS_CONFIG.iteritems():
            if report in selected_reports and \
                    filter(lambda preset: preset in config["meta"]["presets"], selected_presets):
                reports.append(report)
                selected_sheets += return_sheets_by_presets(config["sheet_params"], selected_presets)

        selected_sheets = [sheet_name for i, sheet_name in enumerate(selected_sheets)
                           if sheet_name not in selected_sheets[:i]]
        return selected_sheets, reports

    return possible_sheets


def return_report_sheets(report_name):
    return CLI_REPORTS_CONFIG[report_name]["meta"]["sheet_names"]


def return_show_comments(report_name):
    return CLI_REPORTS_CONFIG[report_name]["meta"]["show_comments"]


def return_sheets_by_presets(sheets, presets=None):
    """sheets - list of dicts()"""

    selected_sheets = []
    for preset in presets:
        preset_sheets = [sheet for sheet in sheets if preset in sheet.values()[0].get("presets", [])]
        selected_sheets += [sheet.keys()[0] for sheet in preset_sheets if sheet.keys() not in selected_sheets]

    return selected_sheets


def return_report_name(report_name):
    with open(ARGS_FILE_PATH) as fd:
        args = json.load(fd)
    lang = args.get("--lang", None)

    if lang is None:
        return report_name
    else:
        return CLI_REPORTS_CONFIG[report_name]["meta"]["ru_name"]


def return_sheet_name(report_name, sheet_name, local=False):
    with open(ARGS_FILE_PATH) as fd:
        args = json.load(fd)
    lang = args.get("--lang", None)

    if lang is None and not local:
        return sheet_name
    elif local:
        try:
            new_name = unicode([sheet.keys()[0] for sheet in CLI_REPORTS_CONFIG[report_name]["sheet_params"]
                                if sheet.values()[0]['ru_name'] == sheet_name][0])
            return new_name
        except IndexError:
            return sheet_name

    new_name = return_sheet_params(CLI_REPORTS_CONFIG[report_name]["sheet_params"],
                                   sheet_name).get("ru_name", sheet_name)

    return new_name


def return_sheet_note(report_name, sheet_name, **kw_args):
    """
    Функция возвращает текст заметки для note_maker'a.
    Если в kw_args переданы startcol, startrow (pa.DataFrame.to_excel)
    и они отличны от 1 (не ячейка "A1"), то возвращается None.
    Также None возвращается, если у листа в sheetx.yml нет ключа ru_note.
    """

    startcol = kw_args.get("startcol", 1)
    startrow = kw_args.get("startcol", 1)
    if startcol == 1 and startrow == 1:
        note_txt = return_sheet_params(CLI_REPORTS_CONFIG[report_name]["sheet_params"], sheet_name).get("ru_note")
        return note_txt
    else:
        return None


def return_sheet_params(sheets, sheet_name):
    """sheets - list of dicts()"""
    return [sheet for sheet in sheets if sheet.keys()[0] == sheet_name][0].values()[0]


def get_reports_config():
    """
    config - {report_name: meta: {ru_name, en_name, presets, sheet_names}, sheet_params: []}
    presets - []
    """

    with open(join(dirname(__file__), "sheets.yml")) as fd:
        reports = yaml.load(fd)
    config = {}
    presets = []
    for report, params in reports.iteritems():
        config[report] = {"meta": params[0].values()[0],
                          "sheet_params": params[1:]}

        config[report]["meta"]["sheet_names"] = sum([sheet.keys() for sheet in config[report]["sheet_params"]], [])

        report_presets = config[report]["meta"].get("presets", [])
        presets += [preset for preset in report_presets if preset not in presets]

    return config, presets


CLI_REPORTS_CONFIG, CLI_PRESETS = get_reports_config()
