#!/usr/bin/env python3
from tkinter import *
import matplotlib.pyplot as plt
from matplotlib.mathtext import math_to_image
from io import BytesIO
from PIL import ImageTk, Image
import numpy as np
import shutil
import pandas as pd
import os
import sys
import locale
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from globalemu.eval import evaluate

l = '.'.join(locale.getlocale())
if l[:2] != 'en':
    try:
        locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8')
    except OSError:
        print("OSError: system locale is not set to 'en_' and " +
              "'en_GB.UTF-8' is not available. This will cause " +
              "issues with tkinter. To install 'en_GB.UTF-8' and run the " +
              "GUI run 'sudo apt-get install language-pack-en' in " +
              "the terminal.")

def slider_var(name, lower, upper, position_y,
             initial, img_x_resize, img_y_resize, tickinterval,
             resolution=0.1):
    """Creates the GUI sliders and associated labels"""
    position_x = 410
    buffer = BytesIO()
    math_to_image(name, buffer, dpi=200, format='png')
    buffer.seek(0)

    img_var = ImageTk.PhotoImage(Image.open(buffer).resize(
        (img_x_resize, img_y_resize)))
    entry = Scale(
                window, from_=lower, to=upper,
                orient=HORIZONTAL, length=325,
                resolution=resolution,
                tickinterval=tickinterval,
                background='white', command=signal)
    entry.place(x=position_x, y=position_y)
    entry.set(initial)
    return entry, img_var

def signal(_, parameters=None):
    """Creates the new signals when the user moves the sliders."""
    if parameters is not None:
        params = []
        for i in range(len(center)):
            if i in set(logs):
                params.append(10**parameters[i])
            else:
                params.append(parameters[i])
    else:
        params = []
        for i in range(len(entries)):
            if i in set(logs):
                params.append(10**float(entries[i].get()))
            else:
                params.append(float(entries[i].get()))
    signal, z = predictor(params)
    plt.figure(figsize=(4, 3))
    plt.plot(z, signal, c='k')
    plt.xlabel('z')
    plt.ylabel(ylabel)
    plt.ylim([label_min, label_max])
    plt.tight_layout()
    plt.savefig('img/img.png', dpi=100)
    plt.close()
    if parameters is None:
        new_img = ImageTk.PhotoImage(Image.open("img/img.png"))
        panel.configure(image=new_img)
        panel.image = new_img


def reset(parameters=None):
    """Resets the GUI when the reset button is pressed."""
    if parameters is not None:
        signal('', parameters)
    else:
        for i in range(len(center)):
            if i in set(logs):
                entries[i].set(center[i])
            else:
                entries[i].set(center[i])
        signal('')

base_dir = sys.argv[1]

config = pd.read_csv(base_dir + 'gui_configuration.csv')

logs = config['logs'].tolist()
logs = [int(x) for x in logs if x != '--']
label_min = config['label_min'][0]
label_max = config['label_max'][0]
ylabel = config['ylabel'][0]

predictor = evaluate(base_dir=base_dir, logs=logs)

window = Tk()
window.geometry("800x450")
window.configure(background='white')

window.title('globalemu GUI')

if os.path.exists('img/'):
    shutil.rmtree('img/')
os.mkdir('img/')

center = []
for i in range(len(config['names'])):
    center.append(config['mins'][i] + (config['maxs'][i] - config['mins'][i])/2)
center = np.array(center)

reset(parameters=center)

img = ImageTk.PhotoImage(Image.open("img/img.png"))
panel = Label(window, image=img)
panel.place(x=10, y=10)

bad_characters = ['$', '\mathrm', '{', '}', '_', '^', '\\']
common_greek = ['tau', 'alpha', 'nu', 'beta']
entries, labels = [], []
for i in range(len(config['names'])):
    for j in range(len(bad_characters)):
        if j == 0:
            reduced_name = config['names'][i].replace(bad_characters[j], '')
        else:
            reduced_name = reduced_name.replace(bad_characters[j], '')
    if reduced_name in set(common_greek):
        reduced_name = 'o'
    e, l = slider_var(config['names'][i], config['mins'][i],
                      config['maxs'][i], 10+60*i,
                      center[i],
                      8*len(reduced_name), 15,
                      (config['maxs'][i] - config['mins'][i])/5,
                      resolution=(config['maxs'][i] - config['mins'][i])/100)
    labels.append(l)
    entries.append(e)

for i in range(len(labels)):
    Label(window, image=labels[i]).place(x=740, y=10+i*60)

btn = Button(window, text='Reset', command=reset)
btn.place(x=180, y=360)

window.mainloop()

shutil.rmtree('img/')
