from typing import Dict
from typing import List
from typing import Tuple
from typing import Optional
import statistics


def compare_alignments(
    alignments_one: Dict[str, List[Tuple[float, float, str]]],
    alignments_two: Dict[str, List[Tuple[float, float, str]]],
    frame_shift: int,
) -> Tuple[int, Optional[float]]:
    """
    Compares two sets of alignments for difference

    Parameters
    ----------
    alignments_one: Dict
        First set of alignments
    alignments_two: Dict
        Second set of alignments
    frame_shift: int
        Frame shift in feature generation, in ms

    Returns
    -------
    int
        Difference in number of aligned files
    float
        Mean boundary difference between the two alignments
    """
    utterances_aligned_diff = len(alignments_two) - len(alignments_one)
    utts_one = set(alignments_one.keys())
    utts_two = set(alignments_two.keys())
    common_utts = utts_one.intersection(utts_two)
    differences = []
    for u in common_utts:
        end = alignments_one[u][-1][1]
        t = 0
        one_alignment = alignments_one[u]
        two_alignment = alignments_two[u]
        difference = 0
        while t < end:
            one_label = None
            two_label = None
            for b, e, l in one_alignment:
                if t < b:
                    continue
                if t >= e:
                    break
                one_label = l
            for b, e, l in two_alignment:
                if t < b:
                    continue
                if t >= e:
                    break
                two_label = l
            if one_label != two_label:
                difference += frame_shift
            t += frame_shift
        difference /= end
        differences.append(difference)
    if differences:
        mean_difference = statistics.mean(differences)
    else:
        mean_difference = None
    return utterances_aligned_diff, mean_difference