from nile.api.v1 import Record


def _assert_all_keys_in_dict(keys, dictionary):
    for key in keys:
        assert key in dictionary, '`{}` key is absent: {}'.format(key, dictionary)


def _assert_only_one_key_in_dict(keys, dictionary):
    number_of_keys_in_dict = sum([key in dictionary for key in keys])
    assert number_of_keys_in_dict == 1, 'One key of {} must be present in {}'.format(keys, dictionary)


def _get_task_prefixes(tariffs):
    _assert_only_one_key_in_dict(['task_prefix', 'task_prefixes'], tariffs)

    if 'task_prefix' in tariffs:
        return [tariffs['task_prefix']]

    assert len(tariffs['task_prefixes']) > 0, 'Prefixes list cannot be empty'
    return tariffs['task_prefixes']


def _make_record(task_id, task_name_tree, seconds):
    assert len(task_name_tree) > 0, "task_name_tree can't be empty"
    return Record(
        task_id=task_id,
        task_name_tree='\t' + '\t'.join(task_name_tree) + '\t',
        seconds_per_task=seconds
    )


def _make_records_for_task(task, task_id, task_name_tree, seconds):
    task_id = task_id + task
    task_name_tree = task_name_tree + [task]
    return [
        _make_record(task_id, task_name_tree[:level], seconds)
        for level in range(1, len(task_name_tree) + 1)
    ]


def _make_records_for_tariff(tariff, date, task_id, task_name_tree):
    result = []

    start_date = tariff.get('start_date')
    if start_date and date < start_date:
        return result

    end_date = tariff.get('end_date')
    if end_date and end_date < date:
        return result

    _assert_all_keys_in_dict(['seconds', 'tariff_name', 'tasks'], tariff)

    seconds = tariff['seconds']
    task_name_tree = task_name_tree + [tariff['tariff_name']]

    assert len(tariff['tasks']) > 0, 'Tasks list is empty in the tariff: {}'.format(tariff)
    for task in tariff['tasks']:
        result += _make_records_for_task(task, task_id, task_name_tree, seconds)
    return result


def _make_records_for_task_prefix(tariffs, date, task_prefix, task_name_tree):
    result = []
    for tariff in tariffs:
        result += _make_records_for_tariff(tariff, date, task_prefix, task_name_tree)
    return result


def make_records(tariffs, date):
    '''
    tariffs: {
        task_group: string,
        task_subgroup: optional<string>,
        task_prefix: string, (or task_prefixes: [string, ...])
        tariffs: [
            {
                tariff_name: string,
                start_date: optional<datetime.date>,
                end_date: optional<datetime.date>,
                seconds: integer,
                tasks: [
                   string,
                   ...
                ]
            },
            ...
        ]
    }

    Result: [
        Record(
            task_id: task_prefix/task
            task_name_tree: all/task_group/task_subgroup/tariff_name/task,
            seconds_per_task: seconds
        ),
        Record(
            task_id: task_prefix/task
            task_name_tree: all/task_group/task_subgroup/tariff_name,
            seconds_per_task: seconds
        ),
        ...
        Record(
            task_id: task_prefix/task
            task_name_tree: all,
            seconds_per_task: seconds
        ),
        ...
    ]
    '''

    _assert_all_keys_in_dict(['task_group', 'tariffs'], tariffs)
    assert len(tariffs['tariffs']) > 0, 'Tariffs list is empty in the tariffs: {}'.format(tariffs)

    task_name_tree = ['all', tariffs['task_group']]
    if 'task_subgroup' in tariffs:
        task_name_tree += [tariffs['task_subgroup']]

    result = []
    for task_prefix in _get_task_prefixes(tariffs):
        result += _make_records_for_task_prefix(tariffs['tariffs'], date, task_prefix, task_name_tree)
    return result
