from typing import *
import os

class MHead:
    format = 0
    tracks = list()
    division = 0

class MTrack:
    data = list()
    
class Midi:
    head: MHead = MHead()
    tracks: List[MTrack] = list()
    

def midi_open(_directory: str):
    if(os.path.exists(_directory)):
        return open(_directory, "rb")
    else:
        print("파일이 존재하지 않습니다.")
        exit()    

def midi_close(_midi):
    _midi.close()

def midi_decompile(_midi):
    midi = Midi()
    
    mode: str = ""
    bytelist: list = list()
    while b := _midi.read(1):
        bytelist.append(b)
        #print(b)
        
        if(mode == ""):
            if(len(bytelist) == 4):
                mode = bytelist_to_ascii(bytelist)
                bytelist.clear()
        
        if(mode == "MThd"):
            _length = int.from_bytes(_midi.read(4), "big")
            _data = _midi.read(_length)
            print("Head Data Length " + str(_length))
            
            midi.head.format = bytelist_to_int(_data[0:2])
            _tracks = bytelist_to_int(_data[2:4])
            for i in range(0, _tracks):
                midi.head.tracks.append(MTrack())
            midi.head.division = bytelist_to_int(_data[4:6])
            
            print("\tFormat: {}".format(midi.head.format), end=" ")
            if(midi.head.format == 0):
                print("(single track)")
            if(midi.head.format == 1):
                print("(multi-sequence track)")
            if(midi.head.format == 2):
                print("(multi track)")
            print("\tTracks: {}".format(_tracks))
            print("\tDivision: {}".format(midi.head.division))
            
            mode = ""
        
        if(mode == "MTrk"):
            _length = int.from_bytes(_midi.read(4), "big")
            _data = _midi.read(_length)
            print("Track Data Length " + str(_length))
            
            mode = ""

def bytelist_to_ascii(_bytelist):
    _s = ""
    for byte in _bytelist:
        try:
            _s += byte.decode("utf-8")
        except:
            print("Decode Failed")
    return _s

def bytelist_to_int(_bytelist):
    return int.from_bytes(_bytelist, byteorder="big", signed=True)

if(__name__ == "__main__"):
    midi = midi_open(r"C:\Users\corin\Desktop\Audio\Forth.mid")
    midi_decompile(midi)
    midi_close(midi)