from __future__ import annotations

from dataclasses import dataclass
from enum import auto
from typing import TYPE_CHECKING

from flexohr.harmony.enums import FancyStrEnum

if TYPE_CHECKING:
    pass


class ToneFunction(FancyStrEnum):
    root = auto()
    bass = auto()
    third = auto()
    fifth = auto()
    seventh = auto()
    ninth = auto()
    eleventh = auto()
    thirteenth = auto()
    leading_tone = auto()
    downward_leading_tone = auto()
    altered = auto()
    added_second = auto()
    added_fourth = auto()
    added_sixth = auto()
    second_suspension = auto()
    fourth_suspension = auto()
    pedal = auto()
    undefined = auto()
    # Aliases
    rt = "root"
    bs = "bass"
    _3rd = "third"
    _5th = "fifth"
    _7th = "seventh"
    _9th = "ninth"
    _11th = "eleventh"
    _13th = "thirteenth"
    lt = "leading_tone"
    dlt = "downward_leading_tone"
    alt = "altered"
    a2 = "added_second"
    a4 = "added_fourth"
    a6 = "added_sixth"
    s2 = "second_suspension"
    s4 = "fourth_suspension"
    suspended_second = "second_suspension"
    suspended_fourth = "fourth_suspension"
    ped = "pedal"
    u = "undefined"


class ChordQuality(FancyStrEnum):
    # Triads
    major_triad = auto()
    minor_triad = auto()
    diminished_triad = auto()
    augmented_triad = auto()
    # Sevenths
    dominant_seventh = auto()
    minor_seventh = auto()
    major_seventh = auto()
    minor_major_seventh = auto()
    diminished_seventh = auto()
    half_diminished_seventh = auto()
    augmented_seventh = auto()
    augmented_major_seventh = auto()
    # Augmented sixths
    italian_sixth = auto()
    german_sixth = auto()
    french_sixth = auto()
    # Suspended
    suspended_second = auto()
    suspended_fourth = auto()
    # Power / single / unclassified
    power_chord = auto()
    unison = auto()
    unclassified = auto()
    # Aliases
    maj = "major_triad"
    min = "minor_triad"
    dim = "diminished_triad"
    aug = "augmented_triad"
    Mm7 = "dominant_seventh"
    mm7 = "minor_seventh"
    MM7 = "major_seventh"
    mM7 = "minor_major_seventh"
    o7 = "diminished_seventh"
    hd7 = "half_diminished_seventh"
    aug7 = "augmented_seventh"
    augM7 = "augmented_major_seventh"
    It6 = "italian_sixth"
    Ger6 = "german_sixth"
    Fr6 = "french_sixth"
    sus2 = "suspended_second"
    sus4 = "suspended_fourth"
    pow = "power_chord"


class ChordClass(FancyStrEnum):
    dyad = auto()
    triad = auto()
    seventh = auto()
    ninth = auto()
    eleventh = auto()
    thirteenth = auto()
    augmented_sixth = auto()
    suspended = auto()
    cluster = auto()
    unclassified = auto()
    # Aliases
    _2 = "dyad"
    _3 = "triad"
    _7th = "seventh"
    _9th = "ninth"
    _11th = "eleventh"
    _13th = "thirteenth"
    aug6 = "augmented_sixth"
    sus = "suspended"
    cl = "cluster"


class Inversion(FancyStrEnum):
    root_position = auto()
    first = auto()
    second = auto()
    third = auto()
    fourth = auto()
    # Aliases
    rp = "root_position"
    _1st = "first"
    _2nd = "second"
    _3rd = "third"
    _4th = "fourth"


class CollectionType(FancyStrEnum):
    # Tone fields
    chromatic = auto()
    octatonic_hw = auto()
    octatonic_wh = auto()
    diatonic = auto()
    whole_tone = auto()
    hexatonic = auto()
    pentatonic = auto()
    # Modal / scale types
    major = auto()
    natural_minor = auto()
    harmonic_minor = auto()
    melodic_minor = auto()
    dorian = auto()
    phrygian = auto()
    lydian = auto()
    mixolydian = auto()
    aeolian = auto()
    locrian = auto()
    major_pentatonic = auto()
    minor_pentatonic = auto()
    # Aliases
    chr = "chromatic"
    oct_hw = "octatonic_hw"
    oct_wh = "octatonic_wh"
    dia = "diatonic"
    wt = "whole_tone"
    hex = "hexatonic"
    pent = "pentatonic"
    M = "major"
    m = "natural_minor"
    hm = "harmonic_minor"
    mm = "melodic_minor"
    dor = "dorian"
    phr = "phrygian"
    lyd = "lydian"
    mix = "mixolydian"
    aeo = "aeolian"
    loc = "locrian"
    Mp = "major_pentatonic"
    mp = "minor_pentatonic"


class KeyMode(FancyStrEnum):
    major = auto()
    minor = auto()
    # Aliases
    M = "major"
    m = "minor"


@dataclass(frozen=True)
class ToneModification:
    """Modification to a tone beyond the base chord quality."""

    tone_function: ToneFunction
    alteration: object = None  # SIC when pitchspace available
    added: bool = False
    replacement: object = None  # AbsentComponent when applicable
