#! /usr/bin/env python
import os
try:
    import json
except ImportError:
    raise SystemExit, "please install package python-simplejson"

non_preset = set((
    "jconv.expander",
    "crybaby.dialog",
    "compressor.dialog",
    "jconv.dialog",
    "ui.skin",
    "chorus.dialog",
    "system.midistat",
    "ui.main_expander",
    "distortion.dialog",
    "midi_out.dialog",
    "IR.dialog",
    "ui.latency_nowarn",
    "system.waveview",
    "jconv.filedialog",
    "system.fConsta1t",
    "freeverb.dialog",
    ))

old_vars = [
    "amp.feedback",
    "amp.tone.treble",
    "amp.tone.middle",
    "preamp.on_off",
    "amp.in_level",
    "distortion.trigger",
    "distortion.vibrato",
    "distortion.low_highpass.low_freq",
    "distortion.low_highpass.high_freq",
    "distortion.low_highpass.on_off",
    "distortion.low_highcutoff.high_freq",
    "distortion.low_highcutoff.low_freq",
    "distortion.low_highcutoff.on_off",
    "distortion.level",
    "distortion.drive",
    "distortion.gain",
    "distortion.on_off",
    "crybaby.wah",
    "crybaby.level",
    "crybaby.wet_dry",
    "crybaby.on_off",
    "freeverb.wet_dry",
    "freeverb.damp",
    "freeverb.RoomSize",
    "freeverb.on_off",
    "amp.out_master",
    "echo.time",
    "echo.percent",
    "echo.on_off",
    "IR.bandwidth",
    "IR.freq",
    "IR.peak",
    "IR.on_off",
    "amp.feedforward",
    "jconv.wet_dry",
    "amp.balance",
    "ui.main_expander",
    "jconv.expander",
    "jconv.filedialog",
    "distortion.dialog",
    "freeverb.dialog",
    "IR.dialog",
    "crybaby.dialog",
    "midi_out.dialog",
    "system.fConsta1t",
    "midi_out.channel_1.velocity",
    "midi_out.channel_1.sensity",
    "midi_out.channel_1.oktave",
    "midi_out.channel_1.channel",
    "midi_out.channel_1.program",
    "midi_out.channel_2.velocity",
    "midi_out.channel_2.sensity",
    "midi_out.channel_2.oktave",
    "midi_out.channel_2.channel",
    "midi_out.channel_2.program",
    "midi_out.channel_2.on_off",
    "beat_detector.note_off",
    "beat_detector.beat_gain",
    "beat_detector.stepper",
    "midi_out.channel_3.velocity",
    "midi_out.channel_3.sensity",
    "midi_out.channel_3.oktave",
    "midi_out.channel_3.program",
    "midi_out.channel_3.channel",
    "midi_out.channel_3.on_off",
    "beat_detector.atack_gain",
    "system.midistat",
    "midi_out.channel_1.volume",
    "midi_out.channel_2.volume",
    "midi_out.channel_3.volume",
    "midi_out.channel_1.auto_pitch",
    "midi_out.channel_2.auto_pitch",
    "midi_out.channel_3.auto_pitch",
    "compressor.threshold",
    "compressor.attack",
    "compressor.release",
    "compressor.knee",
    "compressor.ratio",
    "compressor.dialog",
    "compressor.on_off",
    "overdrive.drive",
    "overdrive.on_off",
    "system.waveview",
    "anti_aliase.on_off",
    "anti_aliase.feedback",
    "tube.fuzzy",
    "tube.on_off",
    "drive.value",
    "drive.on_off",
    "midi_out.channel_1.autogain",
    "midi_out.channel_2.autogain",
    "midi_out.channel_3.autogain",
    "tube.vibrato.on_off",
    "tube.vibrato",
    "preamp.atan",
    "ui.latency_nowarn",
    "amp.oversample.on_off",
    "amp.threshold",
    "amp.fuzz",
    "tube2.on_off",
    "tube2.resonanz",
    "tube2.vibrato",
    "tube2.fuzzy",
    "amp.tone.bass",
    "shaper.on_off",
    "shaper.sharper",
    "amp.bass_boost.on_off",
    "noise_gate.on_off",
    "noise_gate.threshold",
    "crybaby.autowah",
    "beat_detector.midi_gain",
    "chorus.freq",
    "chorus.depth",
    "chorus.delay",
    "chorus.level",
    "chorus.on_off",
    "chorus.dialog",
    "jconv.left_gain",
    "jconv.left_delay",
    "jconv.right_delay",
    "jconv.right_gain",
    "jconv.dialog",
    "crybaby.position",
    "overdrive.position",
    "distortion.position",
    "freeverb.position",
    "IR.position",
    "compressor.position",
    "echo.position",
    "chorus.position",
    "delay.position",
    "delay.delay",
    "delay.on_off",
    "delay.gain",
    "IR.auto_freq",
    "MultiBandFilter.f16k",
    "MultiBandFilter.f8k",
    "MultiBandFilter.f4k",
    "MultiBandFilter.f2k",
    "MultiBandFilter.f1k",
    "MultiBandFilter.f500",
    "MultiBandFilter.f250",
    "MultiBandFilter.f125",
    "MultiBandFilter.f62_5",
    "MultiBandFilter.f31_25",
    "MultiBandFilter.on_off",
    "convolve.on_off",
    "convolve.select",
    "ui.skin",
    "jconv.on_off",
    ]

head = ["guitarix_file_version", [0, 0, "0.05.4-1"]]

def int_list(l):
    return [int(v) for v in l]

def float_list(l):
    return [float(v) for v in l]

def add_jconv(fn, out_dict):
    if not os.path.exists(fn):
        return out_dict
    d = {}
    for line in file(fn):
        a = line.split()
        cmd = a[0]
        if cmd == "/cd":
            d["jconv.IRDir"] = a[1]
        elif cmd == "/convolver/new":
            d["jconv.BufferSize"], d["jconv.Mem"] = int_list(a[3:])
        elif cmd == "/impulse/read":
            if a[1] == "1":
                d["jconv.Gain"], d["jconv.Delay"], d["jconv.Offset"], d["jconv.Length"] = int_list(a[3:7])
                d["jconv.IRFile"] = a[8]
            else:
                d["jconv.lGain"], d["jconv.lDelay"] = int_list(a[3:5])
                d["jconv.Mode"] = 1
        elif cmd == "/impulse/copy":
            d["jconv.Mode"] = 0
    out_dict["jconv"] = d
    return out_dict

def conv_varlist(l, preset):
    d = {}
    for k, v in zip(old_vars, float_list(l)):
        if (preset and k in non_preset) or (not preset and k not in non_preset):
            continue
        d[k] = v
    return d

def convert_presets():
    fn = "guitarixprerc"
    if not os.path.exists(fn):
        print "no presets file"
        return
    presets = head[:]
    names = []
    for line in file(fn):
        a = line.split()
        nm = a[0]
        names.append(nm)
        presets.append(nm)
        d = dict(engine=conv_varlist(a[1:], True))
        presets.append(add_jconv("jconv_%s.conf" % nm, d))
    print "%d presets found: %s" % (len(names), ", ".join(names))
    json.dump(presets, file("guitarixpre_rc","w"))

def load_corrupt_json_midi_file(f):
    f.next()
    for line in f:
        if line.strip() == "]":
            return
        a = line.split(None, 1)
        yield int(a[0].rstrip(", "))
        yield json.loads(a[1].rstrip(", \n"))

def midi(fn):
    if not os.path.exists(fn):
        return []
    def ll():
        #l = json.load(file(fn))
        l = list(load_corrupt_json_midi_file(file(fn)))
        for i in range(0, len(l), 2):
            yield l[i], l[i+1]
    outl = []
    for v1, v2 in ll():
        if v2[0][0] in ("T","C"):
            ls = []
            for v in v2:
                del v[0]
                v[0] = old_vars[v[0]]
                ls.append(v)
            v2 = ls
        outl.append(v1)
        outl.append(v2)
    return outl

def convert_state():
    fn = "guitarixrc"
    if not os.path.exists(fn):
        print "no state file"
        return
    state = head[:]
    l = file(fn).read().split()
    dp = dict(engine=conv_varlist(l, True))
    add_jconv("jconv_set.conf", dp)
    ds = conv_varlist(l, False)
    state.extend(["current_preset", dp,
                  "settings", ds,
                  "midi_controller", midi("guitarix_midi_rc"),
                  ])
    json.dump(state, file("guitarix_rc","w"))

def main():
    gxpath = os.path.join(os.environ["HOME"], ".guitarix")
    if not os.path.exists(gxpath):
        print "%s doesn't exist, nothing done" % gxpath
        raise SystemExit
    os.chdir(gxpath)
    convert_presets()
    convert_state()
    print "done."

def param_range(a, b):
    for i in range(a+1, b):
        print old_vars[i];

if __name__ == '__main__':
    main()
