import inspect
from unittest import TestCase

from musicscore import C, B, G, Part, Chord, Score, Time
from musicscore.tests.util import generate_path
from musicxml.xmlelement.xmlelement import XMLNotehead


class TestMidiNotes(TestCase):
    def test_midi_note(self):
        m = C(4, "s")
        assert m.accidental.get_pitch_parameters() == ("C", 1, 4)
        m = C(0)
        assert m.accidental.get_pitch_parameters() == ("C", 0, 0)
        with self.assertRaises(ValueError):
            B(-1)
        with self.assertRaises(ValueError):
            G(9, "s")

    def test_midi_note_half_tone_accidentals(self):
        signs = [
            "double-flat",
            "flat-flat",
            "ff",
            "bb",
            "flat",
            "f",
            "b",
            "sharp",
            "s",
            "#",
            "double-sharp",
            "sharp-sharp",
            "ss",
            "##",
        ]
        for sign in signs:
            m = C(4, sign)
            if sign in ["double-flat", "flat-flat", "ff", "bb"]:
                assert m.value == 58
                assert m.accidental.get_pitch_parameters() == ("C", -2, 4)
                assert m.accidental.sign == "flat-flat"

            elif sign in ["flat", "f", "b"]:
                assert m.value == 59
                assert m.accidental.sign == "flat"
                assert m.accidental.get_pitch_parameters() == ("C", -1, 4)
            elif sign in ["sharp", "s", "#"]:
                assert m.value == 61
                assert m.accidental.sign == "sharp"
                assert m.accidental.get_pitch_parameters() == ("C", 1, 4)
            elif sign in ["double-sharp", "sharp-sharp", "ss", "##"]:
                assert m.value == 62
                assert m.accidental.sign == "double-sharp"
                assert m.accidental.get_pitch_parameters() == ("C", 2, 4)

    def test_midi_note_quarter_tones(self):
        m1 = C(4, "three-quarters-flat")
        assert m1.value == 60 - 3 / 2
        assert m1.accidental.sign == "three-quarters-flat"
        assert m1.accidental.get_pitch_parameters() == ("C", -1.5, 4)
        C(4, "quarter-flat")
        C(4, "quarter-sharp")
        C(4, "three-quarters-sharp")

    def test_midi_note_copy(self):
        m = C(4, "#")
        m.add_tie("start")
        copied = m.__copy__()
        assert m != copied
        assert m.value == copied.value
        assert id(m.accidental) == id(copied.accidental)
        assert id(m._ties) == id(copied._ties)

        copied = m.__deepcopy__()
        assert m != copied
        assert m.value == copied.value
        assert m.accidental != copied.accidental
        assert m.accidental.mode == copied.accidental.mode
        assert m.accidental.show == copied.accidental.show
        assert id(m._ties) != id(copied._ties)
        assert m._ties == copied._ties

        copied = m._copy_for_split()
        assert m != copied
        assert m.value == copied.value
        assert m.accidental != copied.accidental
        assert m.accidental.mode == copied.accidental.mode
        assert m.accidental.show == copied.accidental.show
        assert id(m._ties) != id(copied._ties)
        assert m._ties != copied._ties

        #
        # copied = m.__deepcopy__()
        # assert m != copied
        # assert m.value == copied.value
        # assert m.accidental != copied.accidental
        # assert m.accidental.mode == copied.accidental.mode
        # assert m.accidental.show == copied.accidental.show


class TestMidiNoteNoteHead(TestCase):
    def test_notehead_property(self):
        m = C(4)
        m.notehead = "square"
        assert isinstance(m.notehead, XMLNotehead)
        assert m.notehead.value_ == "square"

    def test_notehead_after_finalize(self):
        p = Part("p1")
        ch = Chord(C(4), 1)
        ch.midis[0].notehead = "square"
        p.add_chord(ch)
        p.finalize()
        assert ch.midis[0].parent_note.xml_notehead.value_ == "square"

    def test_notehead_copy_for_split(self):
        midi = C(4)
        midi.notehead = "square"
        copied = midi._copy_for_split()
        assert copied.notehead.value_ == "square"

    def test_midi_note_notehead_after_split(self):
        s = Score()
        p = s.add_part("p1")
        ch = Chord(C(4), 3)
        ch.midis[0].notehead = "square"
        p.add_measure(Time(2, 4))
        p.add_chord(ch)
        path = generate_path(inspect.currentframe())
        s.export_xml(path)
        assert p.get_chords()[1].midis[0].notehead.value_ == "square"
        assert p.get_chords()[1].midis[0].parent_note.xml_notehead.value_ == "square"
