import csv,os

def gen_sample_midi_events(pitch,velA,note_on_sec,note_off_sec,dampFl):

    markA = []
    msgA  = []
    tpqn  = 1260
    bpm   = 60

    ticks_per_sec      = tpqn * bpm / 60.0
    ticks_per_note_on  = ticks_per_sec * note_on_sec
    ticks_per_note_off = ticks_per_sec * note_off_sec
    uid                = 0
    dticks             = 0
    cur_sec            = 0;
    
    r = { 'uid':len(msgA),
           'tpQN':tpqn,
           'bpm':bpm,
           'dticks':0,
           'ch':None,
           'status':None,
           'd0':None,
           'd1':None }

    msgA.append(r);

    for vel in velA:

        ch     = 0
        note_status = 0x90
        ctl_status = 0xb0
        damp_ctl   = 0x40
        
        if dampFl:
            r = { 'uid':len(msgA),
                  'tpQN':None,
                  'bpm':None,
                  'dticks':dticks,
                  'ch':ch,
                  'status':ctl_status,
                  'd0':damp_ctl,
                  'd1':65 }
            
            msgA.append(r)
            dticks = 0

        
        
        r = { 'uid':len(msgA),
               'tpQN':None,
               'bpm':None,
               'dticks':dticks,
               'ch':ch,
               'status':note_status,
               'd0':pitch,
               'd1':vel }

        msgA.append(r)

        dticks = ticks_per_note_on
        
        r  = { 'uid':len(msgA),
               'tpQN':None,
               'bpm':None,
               'dticks':dticks,
               'ch':ch,
               'status':note_status,
               'd0':pitch,
               'd1':0 }
        
        msgA.append(r)

        if dampFl:
            r  = { 'uid':len(msgA),
                   'tpQN':None,
                   'bpm':None,
                   'dticks':0,
                   'ch':ch,
                   'status':ctl_status,
                   'd0':damp_ctl,
                   'd1':0 }
            
            msgA.append(r)
        
        dticks = ticks_per_note_off

        markA.append( (cur_sec, cur_sec+note_on_sec, vel) )

        cur_sec += note_on_sec + note_off_sec

    return msgA,markA

def write_file( fname, msgA ):

    fieldnames = list(msgA[0].keys())

    with open(fname,"w") as f:
        wtr = csv.DictWriter(f, fieldnames=fieldnames)

        wtr.writeheader()

        for m in msgA:
            wtr.writerow(m)
        
def write_marker_file(fname, markA ):

    with open(fname,"w") as f:
        for beg_sec,end_sec,vel in markA:
            f.write(f"{beg_sec}\t{end_sec}\t{vel}\n")
    
def gen_midi_csv_and_marker_files( pitch, velA, note_on_sec, note_off_sec, damp_fl, out_dir ):

    if not os.path.isdir(out_dir):
        os.mkdir(out_dir)
    
    msgA,markA = gen_sample_midi_events(pitch,velA,note_on_sec,note_off_sec,damp_fl)

    damp_label = "damp_" if damp_fl else ""
    
    midi_csv_fname = os.path.join(out_dir,f"{pitch:03}_{damp_label}sample.csv")
    mark_fname     = os.path.join(out_dir,f"{pitch:03}_{damp_label}marker.txt")

    write_file(midi_csv_fname,msgA)
    write_marker_file(mark_fname,markA)

    return midi_csv_fname, mark_fname

def gen_complete_midi_csv( pitchA, velA, note_on_sec, note_off_sec, out_fname ):
    damp_fl = False
    msgL = []
    for i,pitch in enumerate(pitchA):
        msgA,_ = gen_sample_midi_events(pitch,velA,note_on_sec,note_off_sec,damp_fl)
        if i > 0:
            msgA = msgA[1:]
        msgL += msgA
        
    write_file(out_fname,msgL)

if __name__ == "__main__":

    # min_pitch      = 21
    # max_pitch      = 108
    
    out_dir       = "/home/kevin/temp"
    dampFl        = False
    velA          = [ 1,5,10,16,21,26,32,37,42,48,53,58,64,69,74,80,85,90,96,101,106,112,117,122,127]
    note_off_sec  = 2.0

    if False:
        pitchL        = [ 21, 60 ]
        noteDurL      = [ 20.0, 20.0 ]
        
    if True:
        pitchL = [ i for i in range(21,109) ]
        noteDurL = [ 20.0 for _ in range(len(pitchL)) ]
        
    if False:
        dampFlL       = [ False, True ] if dampFl else [ False ]

        for pitch,note_on_sec in zip(pitchL,noteDurL):
            for damp_fl in dampFlL:
                csv_fname, mark_fname = gen_midi_csv_and_marker_files( pitch, velA, note_on_sec, note_off_sec, damp_fl, out_dir )

    if True:
        note_on_sec = 5
        note_off_sec = 1
        out_fname = "/home/kevin/temp/all_midi.csv"
        gen_complete_midi_csv(pitchL, velA, note_on_sec, note_off_sec, out_fname)