from typing import Dict
from typing import Tuple
from typing import List


def schedule_ordering(schedules_by_cohort: Dict) -> Tuple[List, Dict]:
    """Assigns a canonical ordering to unique schedules across cohorts.

    Multiple cohorts may share the same schedule. In order to minimize the size
    of the assignment problem, we assign an ID to each unique schedule.

    Args:
        schedules_by_cohort: A dictionary with cohort names as the keys and
            lists of schedules as the values.

    Returns:
        A tuple containing:
            * A list of unique schedules, indexed by schedule IDs.
            * A modified version of `schedules_by_cohort`. Each schedule
              is replaced with a wrapper dictionary with an `id` field
              (the unique ID of the schedule) and a `blocks` field
              (the original schedule data).
    """
    schedule_ids: Dict[Tuple, int] = {}
    schedules_by_id = []
    schedules_by_cohort_with_id = {}
    sched_id = 0
    for cohort, schedules in schedules_by_cohort.items():
        with_ids = []
        for schedule in schedules:
            uniq = []
            for block in schedule:
                block_hash = (block['start'], block['end'], block['site'])
                uniq += list(block_hash)
            uniq_hash = tuple(uniq)
            if uniq_hash in schedule_ids:
                with_ids.append({
                    'id': schedule_ids[uniq_hash],
                    'blocks': schedule
                })
            else:
                schedule_ids[uniq_hash] = sched_id
                schedules_by_id.append(schedule)
                with_ids.append({'id': sched_id, 'blocks': schedule})
                sched_id += 1
        schedules_by_cohort_with_id[cohort] = with_ids
    return schedules_by_id, schedules_by_cohort_with_id