import sys
import os
import json
import tkinter as tk

from tkinter import simpledialog
from tkinter import messagebox

values = [0,0,0,0,0,3300,3300,3300,3300,3300,'0']

class ModelSelector(tk.simpledialog.Dialog):
    ''' Dialog per selezionare modelli di suoni. '''
    def __init__(self, parent, cache):
        self.cache = cache
        self.model = None
        super().__init__(parent, title='Scelta modello')

    def body(self, frame):
        self.frame = frame
        self.lst = tk.Listbox(frame)
        self.lst.grid(row=0, column=0, padx=(5,1), pady=5, sticky='nsew')
        vscrol = tk.Scrollbar(frame, orient=tk.VERTICAL,
                              command=self.lst.yview)
        self.lst.configure(yscrollcommand=vscrol.set)
        vscrol.grid(row=0, column=1, padx=(1,5), pady=5, sticky='ns')

        frame.grid_rowconfigure(0, weight=1)
        frame.grid_columnconfigure(0, weight=1)
        self._load_models()
        return frame

    def buttonbox(self):
        pn_cmd = tk.Frame(self.frame)
        pn_cmd.grid(row=1, column=0, columnspan=2, sticky='ew')
        bt_ok = tk.Button(pn_cmd, text='Ok', command=self._on_ok)
        bt_ok.grid(row=0, column=0, padx=5, pady=5, sticky='ew')
        bt_cancel = tk.Button(pn_cmd, text='Annulla', command=self._on_cancel)
        bt_cancel.grid(row=0, column=1, padx=5, pady=5, sticky='ew')
        pn_cmd.grid_columnconfigure(0, weight=1, uniform='bt')
        pn_cmd.grid_columnconfigure(1, weight=1, uniform='bt')
        

    def _on_ok(self):
        sel = self.lst.curselection()
        if not sel: return
        idx = sel[0]
        value = self.lst.get(idx)
        if value:
            self.model = value
            self.destroy()

    def _on_cancel(self):
        self.destroy()

    def _load_models(self):
        contents = os.listdir(self.cache)
        models = [x.split('.')[0] for x in contents if x.endswith('.json')]
        for m in models:
            self.lst.insert(tk.END, m)

def select_model(app, cache):
    dialog = ModelSelector(app, cache)
    return dialog.model
    

class MainWin(tk.Tk):
    freqs = ['1','2','3','4','5']
    mixer = ['1','2','3','4','5']
    shape = ['1','2','3','4','5']
    def __init__(self):
        super().__init__()
        self._cache = ''
        self._model = ''
        self._set_environment()
        self._make_menus()
        self.populate()

    def _set_environment(self):
        ''' Stabilisce la posizione di storage dei modelli di combinazioni. '''
        # stabilisce la locazione per la cache in una sub-directory
        # della cartella contenente lo script denominata "Modelli"
        app_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
        self._cache = os.path.join(app_dir, 'Modelli')
        # se la sub-directory non esiste la crea
        if not os.path.exists(self._cache) and not os.path.isdir(self._cache):
            os.mkdir(self._cache)
        
    def _make_menus(self):
        ''' Costruisce un sistema di menu per la finestra. '''        
        menubar = tk.Menu(self, bg='black', fg='white',
                          activebackground='blue', activeforeground='white')
        filemenu = tk.Menu(menubar, bg='black', fg='white',
                          activebackground='blue', activeforeground='white')
        filemenu.add_command(label="New", command=self._on_initialize)
        filemenu.add_separator()
        filemenu.add_command(label="Open", command=self._on_open)
        filemenu.add_separator()
        filemenu.add_command(label="Save", command=self._on_save)
        filemenu.add_command(label="Save As ...",  command=self._on_save_as)
        filemenu.add_separator()
        filemenu.add_command(label="Close", command=self.destroy)
        menubar.add_cascade(label="File", menu=filemenu)
        self.config(menu=menubar)
        
    def populate(self):
        self.title(' SINTHETIZER')
        self.configure(bg='black')
        self._scales = {'freqs': [],
                        'mixer': [], 
                        'shape': []}
        st_pnl = tk.LabelFrame(self, text='', fg='white', background='black')
        st_pnl.pack(padx=5, pady=5)
        st_pnl.grid(row=0, column=0, sticky='nsew')
        self.v_scales = []
        self.h_scales = []
        #for i in range(len(self.shape)):
         #   lbl = tk.Label(st_pnl, text=self.adsrv[i], background='black', fg='white', pady=10, padx=10, font=10)
          #  lbl.grid(row=0, column=i, padx=12, pady=50, sticky='ne')
           # sc = tk.Scale(st_pnl, from_=25, to=1, showvalue=True,  length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
            #sc.set(0)
            #sc.bind("<ButtonRelease>", self.aggiorna_adsrv)       #binding  adsrv
            #sc.grid(row=2, column=i, padx=10, pady=10, sticky='ne')
            #st_pnl.grid_columnconfigure(i, weight=1)
            #self._scales['adsrv'].append(sc)
        st_pnl.grid_rowconfigure(1, weight=1)
        fr_pnl = tk.LabelFrame(self, text=' Frequency (Hz)', fg="white", background="black")
        fr_pnl.grid(row=0, column=1, sticky='nsew')
        for i in range(len(self.freqs)):
            #lbl = tk.Label(fr_pnl, text=self.freqs[i], fg='white', background="black")
            #lbl.grid(row=0, column=i, padx=5, pady=50, sticky='ne')
            sc = tk.Scale(fr_pnl, from_=1500, to=0, showvalue=True, length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
            sc.set(0)
            sc.bind("<ButtonRelease>", self.aggiorna_freq)       #binding  freq
            sc.grid(row=2, column=i, padx=10, pady=10, sticky='se')
            self._scales['freqs'].append(sc)
            fr_pnl.grid_columnconfigure(i, weight=1, uniform='fsc')
        fr_pnl.grid_rowconfigure(1, weight=1)
        #fr = tk.LabelFrame(self, text='LFO1 for FM (Hz)', fg="white", background="black")
        #fr.grid(row=1, column=0, sticky='se')
        #for i in range(len(self.lfo1)):
         #   sc= tk.Scale(fr, from_=50, to=0, showvalue=True, length=200, tickinterval=1, bg='black', fg='white', orient=tk.VERTICAL)
          #  sc.set(0)
           # sc.bind("<ButtonRelease>", self.aggiorna_lfo1)       #binding lfo1
            #sc.grid(row=0, column=0, padx=10, pady=10, sticky='se')
            #self._scales['lfo1'].append(sc)
        fr_pnl = tk.LabelFrame(self, text=' Mixer (ohms)', fg="white", background="black")
        fr_pnl.grid(row=1, column=1, sticky='ew')
        for i in range(len(self.mixer)):
            lbl = tk.Label(fr_pnl, text=self.mixer[i], fg="white", background="black")
            lbl.grid(row=1, column=i, padx=10, pady=10, sticky='se')
            sc = tk.Scale(fr_pnl, from_=100000, to=0, showvalue=True, length=200, tickinterval=1,background='black', fg='white', orient=tk.VERTICAL)
            sc.set(0)
            sc.bind("<ButtonRelease>", self.aggiorna_mixer)       #binding mixer
            sc.grid(row=1, column=i, padx=10, pady=10, sticky='se')
            self._scales['mixer'].append(sc)   

        self.grid_columnconfigure(0, weight=1)

    def _on_initialize(self):
        ''' Imposta lo stato iniziale per un nuovo modello di frequenze. '''
        self._model = ''
        for s in self._scales['freqs']:
            s.set(0)
        for s in self._scales['mixer']:
            s.set(0)

    def _on_save(self):
        if not self._model:
            name = simpledialog.askstring('Nome modello', 'inserire il nome da assegnare', parent=self)
            if not name:
                return
            self._model = os.path.join(self._cache, name + '.json')
        if os.path.exists(self._model):
            msg = 'Nome modello già in uso'
            messagebox.showerror('Duplicazione', msg, parent=self)
            return
        values = {}
        for k in self._scales.keys():
            sets = []
            for i in range(len(self._scales[k])):
                sets.append(self._scales[k][i].get())
            values[k] = sets
        try:
            with open(self._model, 'w') as f:
                json.dump(values, f)
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return

    def _on_save_as(self):
        if not self._model:
            msg = 'Questo modello non ha nome, utilizzare il comando "save"'
            messagebox.showinfo('Comando improprio', msg, parent=self)
            return
        name = simpledialog.askstring('Nome modello', 'inserire il nome da assegnare', parent=self)
        if not name:
            return
        name = os.path.join(self._cache, name + '.json')
        if os.path.exists(name):
            msg = 'Nome modello già in uso'
            messagebox.showerror('Duplicazione', msg, parent=self)
            return
        self._model = name
        values = {}
        for k in self._scales.keys():
            sets = []
            for i in range(len(self._scales[k])):
                sets.append(self._scales[k][i].get())
            values[k] = sets
        try:
            with open(self._model, 'w') as f:
                json.dump(values, f)
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return        

    def _on_open(self):
        model = select_model(self, self._cache)
        if not model: return
        self._model = os.path.join(self._cache, model + '.json')
        try:
            with open(self._model) as f:
                values = json.load(f)    
        except OSError as e:
            msg = 'Errore salvataggio dati mixer:\n\n' + repr(e)
            messagebox.showerror('Errore I/O', msg, parent=self)
            return
        for k in self._scales.keys():
            data = values[k]   #data è il dizionario degli slader
            print(values[k])
            for i in range(len(self._scales[k])):
                self._scales[k][i].set(data[i])
                
    
    def aggiorna_freq(self, evt):
        w = evt.widget
        try:
            index= self._scales['freqs'].index(w)
            values[index] = w.get()
            for index in range(0,5):
                print(index, '=>', values[index])
        except ValueError as e:
            return                        

    def aggiorna_mixer(self, evt):
        w = evt.widget
        try:
            index = self._scales['mixer'].index(w)
            values[index + 5] = w.get()
            for index in range(5,10):
                print(index, '=>', values[index])
        except ValueError as e:
            return           

if __name__ == '__main__':
    #crea finestra
    app = MainWin()
    app1 = MainWin()
    app.configure(background='black')
    app.geometry("1000x1000+0+0")
    app.resizable(False,False)
    app.configure(background="black")
    app.mainloop()
    app1.populate()
    

   

    

