import difflib, click

from enum import Enum


class TrackDisposition(Enum):

    DEFAULT             = {"name": "default", "index": 0, "indicator": "DEF"}
    FORCED              = {"name": "forced", "index": 1, "indicator": "FOR"}

    DUB                 = {"name": "dub", "index": 2, "indicator": "DUB"}
    ORIGINAL            = {"name": "original", "index": 3, "indicator": "ORG"}
    COMMENT             = {"name": "comment", "index": 4, "indicator": "COM"}
    LYRICS              = {"name": "lyrics", "index": 5, "indicator": "LYR"}
    KARAOKE             = {"name": "karaoke", "index": 6, "indicator": "KAR"}
    HEARING_IMPAIRED    = {"name": "hearing_impaired", "index": 7, "indicator": "HIM"}
    VISUAL_IMPAIRED     = {"name": "visual_impaired", "index": 8, "indicator": "VIM"}
    CLEAN_EFFECTS       = {"name": "clean_effects", "index": 9, "indicator": "CLE"}
    ATTACHED_PIC        = {"name": "attached_pic", "index": 10, "indicator": "ATP"}
    TIMED_THUMBNAILS    = {"name": "timed_thumbnails", "index": 11, "indicator": "TTH"}
    NON_DIEGETICS       = {"name": "non_diegetic", "index": 12, "indicator": "NOD"}
    CAPTIONS            = {"name": "captions", "index": 13, "indicator": "CAP"}
    DESCRIPTIONS        = {"name": "descriptions", "index": 14, "indicator": "DES"}
    METADATA            = {"name": "metadata", "index": 15, "indicator": "MED"}
    DEPENDENT           = {"name": "dependent", "index": 16, "indicator": "DEP"}
    STILL_IMAGE         = {"name": "still_image", "index": 17, "indicator": "STI"}


    def label(self):
        return str(self.value['name'])

    def index(self):
        return int(self.value['index'])

    def indicator(self):
        return str(self.value['indicator'])


    @staticmethod
    def toFlags(dispositionSet):
        """Flags stored in integer bits (2**index)"""

        if type(dispositionSet) is not set:
            raise click.ClickException('TrackDisposition.toFlags(): Argument is not of type set')

        flags = 0
        for d in dispositionSet:
            if type(d) is not TrackDisposition:
                raise click.ClickException('TrackDisposition.toFlags(): Element not of type TrackDisposition')
            flags += 2 ** d.index()
        return flags

    @staticmethod
    def toSet(flags):
        dispositionSet = set()
        for d in TrackDisposition:
            if flags & int(2 ** d.index()):
                dispositionSet.add(d)
        return dispositionSet


    @staticmethod
    def find(label):
        matchingDispositions = [d for d in TrackDisposition if d.label() == str(label)]
        if matchingDispositions:
            return matchingDispositions[0]
        else:
            return None

    @staticmethod
    def fromIndicator(indicator: str):
        matchingDispositions = [d for d in TrackDisposition if d.indicator() == str(indicator)]
        if matchingDispositions:
            return matchingDispositions[0]
        else:
            return None
