#!/ef/efabless/opengalaxy/venv/bin/python3
#
#------------------------------------------------------------
# Profile settings window for the Open Galaxy project manager
#
#------------------------------------------------------------
# Written by Tim Edwards
# efabless, inc.
# July 21, 2017
# Version 0.1
#--------------------------------------------------------

import os
import re
import json
import tkinter
import subprocess
from tkinter import ttk

import og_config

class Profile(tkinter.Toplevel):
    """Open Galaxy project manager profile settings management."""

    def __init__(self, parent=None, fontsize = 11, *args, **kwargs):
        '''See the __init__ for Tkinter.Toplevel.'''
        tkinter.Toplevel.__init__(self, parent, *args, **kwargs)

        s = ttk.Style()
        s.configure('normal.TButton', font=('Helvetica', fontsize), border = 3, relief = 'raised')
        self.protocol("WM_DELETE_WINDOW", self.close)
        self.parent = parent
        self.withdraw()
        self.title('Open Galaxy Project Manager Profile Settings')
        self.sframe = tkinter.Frame(self)
        self.sframe.grid(column = 0, row = 0, sticky = "news")

        self.sframe.stitle = ttk.Label(self.sframe,
		style='title.TLabel', text = 'Profile')
        self.sframe.stitle.grid(column = 0, row = 0, sticky = 'news', padx = 5, pady = 5, columnspan = 2)
        self.sframe.sbar = ttk.Separator(self.sframe, orient='horizontal')
        self.sframe.sbar.grid(column = 0, row = 1, sticky = 'news', padx = 5, pady = 5, columnspan = 2)

        # Read profile JSON file
        self.prefsfile = os.path.expanduser('~/.open_pdks/prefs.json')

        if os.path.exists(self.prefsfile):
            with open(self.prefsfile, 'r') as f:
                prefs = json.load(f)
        else:
            prefs = {}

        # Default font size preference

        self.fontsize = tkinter.IntVar(self.sframe)
        self.sframe.lfsize = ttk.Label(self.sframe, text='Font size', style='blue.TLabel', anchor='e')
        self.sframe.fsize = ttk.Entry(self.sframe, textvariable=self.fontsize)
        self.sframe.lfsize.grid(column = 0, row = 2, sticky = 'news', padx = 5, pady = 5)
        self.sframe.fsize.grid(column = 1, row = 2, sticky = 'news', padx = 5, pady = 5)

        if 'fontsize' in prefs:
            self.fontsize.set(int(prefs['fontsize']))
        else:
            self.fontsize.set(11)

        # User name as written at the top of the project manager and characterization tools

        self.username = tkinter.StringVar(self.sframe)
        self.sframe.luser = ttk.Label(self.sframe, text='User name', style='blue.TLabel', anchor='e')
        self.sframe.user = ttk.Entry(self.sframe, textvariable=self.username)
        self.sframe.luser.grid(column = 0, row = 3, sticky = 'news', padx = 5, pady = 5)
        self.sframe.user.grid(column = 1, row = 3, sticky = 'news', padx = 5, pady = 5)

        if 'username' in prefs:
            self.username.set(prefs['username'])
        else:
            userid = os.environ['USER']
            '''
            p = subprocess.run(['/ef/apps/bin/withnet',
                        og_config.apps_path + '/og_uid_service.py', userid],
                        stdout = subprocess.PIPE)
            
            if p.stdout:
                uid_string = p.stdout.splitlines()[0].decode('utf-8')
                userspec = re.findall(r'[^"\s]\S*|".+?"', uid_string)
                if len(userspec) > 0:
                    username = userspec[0].strip('"')
                    # Note userspec[1] = UID and userspec[2] = role, useful
                    # for future applications.
                else:
                    username = userid
            else:
                username = userid
            '''
            username=userid

            self.username.set(username)

        # Graphics format for magic
        magicgraphics = ['X11', 'CAIRO', 'OPENGL']

        self.maggraph = tkinter.StringVar(self.sframe)
        self.maggraph.set(0)
        self.sframe.lmaggraph = ttk.Label(self.sframe, text='Layout editor graphics format', style='blue.TLabel', anchor='e')
        self.sframe.maggraph = ttk.OptionMenu(self.sframe, self.maggraph,
		self.maggraph.get(), *magicgraphics)

        self.sframe.lmaggraph.grid(column = 0, row = 4, sticky = 'news', padx = 5, pady = 5)
        self.sframe.maggraph.grid(column = 1, row = 4, sticky = 'news', padx = 5, pady = 5)

        if 'magic-graphics' in prefs:
            self.maggraph.set(prefs['magic-graphics'])
        else:
            self.maggraph.set('X11')

        # Choice of layout editor
        layouteditors = ['magic', 'klayout', 'electric']

        self.layouteditor = tkinter.StringVar(self.sframe)
        self.layouteditor.set(0)
        self.sframe.llayouteditor = ttk.Label(self.sframe, text='Layout editor', style='blue.TLabel', anchor='e')
        self.sframe.layouteditor = ttk.OptionMenu(self.sframe, self.layouteditor,
		self.layouteditor.get(), *layouteditors)

        self.sframe.llayouteditor.grid(column = 0, row = 5, sticky = 'news', padx = 5, pady = 5)
        self.sframe.layouteditor.grid(column = 1, row = 5, sticky = 'news', padx = 5, pady = 5)

        if 'layout-editor' in prefs:
            self.layouteditor.set(prefs['layout-editor'])
        else:
            self.layouteditor.set('magic')

        # Choice of schematic editor
        schemeditors = ['electric', 'xschem', 'xcircuit']

        self.schemeditor = tkinter.StringVar(self.sframe)
        self.schemeditor.set(0)
        self.sframe.lschemeditor = ttk.Label(self.sframe, text='Schematic editor', style='blue.TLabel', anchor='e')
        self.sframe.schemeditor = ttk.OptionMenu(self.sframe, self.schemeditor,
		self.schemeditor.get(), *schemeditors)

        self.sframe.lschemeditor.grid(column = 0, row = 6, sticky = 'news', padx = 5, pady = 5)
        self.sframe.schemeditor.grid(column = 1, row = 6, sticky = 'news', padx = 5, pady = 5)

        
        if 'schemeditor' in prefs:
            self.schemeditor.set(prefs['schemeditor'])
        else:
            self.schemeditor.set('electric')

        # Allow the project manager to list development PDKs and create projects
        # using them.

        self.development = tkinter.IntVar(self.sframe)
        self.sframe.ldev = ttk.Label(self.sframe, text='Create projects with development PDKs', style='blue.TLabel', anchor='e')
        self.sframe.dev = ttk.Checkbutton(self.sframe, variable=self.development)
        self.sframe.ldev.grid(column = 0, row = 7, sticky = 'news', padx = 5, pady = 5)
        self.sframe.dev.grid(column = 1, row = 7, sticky = 'news', padx = 5, pady = 5)

        if 'development' in prefs:
            self.development.set(True)
        else:
            self.development.set(False)

        # Allow the synthesis tool to list PDK development standard cell sets

        self.devstdcells = tkinter.IntVar(self.sframe)
        self.sframe.ldev = ttk.Label(self.sframe, text='Use development libraries for digital synthesis', style='blue.TLabel', anchor='e')
        self.sframe.dev = ttk.Checkbutton(self.sframe, variable=self.devstdcells)
        self.sframe.ldev.grid(column = 0, row = 8, sticky = 'news', padx = 5, pady = 5)
        self.sframe.dev.grid(column = 1, row = 8, sticky = 'news', padx = 5, pady = 5)

        if 'devstdcells' in prefs:
            self.devstdcells.set(True)
        else:
            self.devstdcells.set(False)

        # Button bar

        self.bbar = ttk.Frame(self)
        self.bbar.grid(column = 0, row = 1, sticky = "news")

        self.bbar.save_button = ttk.Button(self.bbar, text='Save',
		command=self.save, style = 'normal.TButton')
        self.bbar.save_button.grid(column=0, row=0, padx = 5)

        self.bbar.close_button = ttk.Button(self.bbar, text='Close',
		command=self.close, style = 'normal.TButton')
        self.bbar.close_button.grid(column=1, row=0, padx = 5)

    def save(self):
        # Create JSON record of options and write them to prefs.json
        with open(self.prefsfile, 'w') as f:
            prefs = {}
            prefs['fontsize'] = self.get_fontsize()
            prefs['username'] = self.get_username()
            prefs['schemeditor'] = self.get_schemeditor()
            prefs['magic-graphics'] = self.get_magic_graphics()
            prefs['development'] = self.get_development()
            prefs['devstdcells'] = self.get_devstdcells()
            json.dump(prefs, f, indent = 4)
        # Live-updates where easy. Due read_prefs, a magic-graphics takes effect immediately.
        self.parent.read_prefs()
        self.parent.refreshToolTips()

    def grid_configure(self, padx, pady):
        pass

    def redisplay(self):
        pass

    def get_fontsize(self):
        # return the fontsize value
        return self.fontsize.get()

    def get_username(self):
        # return the username
        return self.username.get()

    def get_schemeditor(self):
        # return the state of the "keep simulation files" checkbox
        return self.schemeditor.get()

    def get_magic_graphics(self):
        # return the format of graphics to use in Magic
        return self.maggraph.get()

    def get_development(self):
        # return the T/F value for creating projects with development PDKs
        return self.development.get()

    def get_devstdcells(self):
        # return the T/F value for synthesizing projects with development standard cells
        return self.devstdcells.get()

    def refresh(self):
        self.prefsfile = os.path.expanduser('~/.open_pdks/prefs.json')

        if os.path.exists(self.prefsfile):
            with open(self.prefsfile, 'r') as f:
                prefs = json.load(f)
        else:
            prefs = {}
        if 'fontsize' in prefs:
            self.fontsize.set(int(prefs['fontsize']))
        else:
            self.fontsize.set(11)
        if 'username' in prefs:
            self.username.set(prefs['username'])
        else:
            userid = os.environ['USER']
        if 'magic-graphics' in prefs:
            self.maggraph.set(prefs['magic-graphics'])
        else:
            self.maggraph.set('X11')
        if 'layout-editor' in prefs:
            self.layouteditor.set(prefs['layout-editor'])
        else:
            self.layouteditor.set('magic')
        if 'schemeditor' in prefs:
            self.schemeditor.set(prefs['schemeditor'])
        else:
            self.schemeditor.set('electric')
        if 'development' in prefs:
            self.development.set(True)
        else:
            self.development.set(False)
        if 'devstdcells' in prefs:
            self.devstdcells.set(True)
        else:
            self.devstdcells.set(False)
    
    def close(self):
        # pop down profile settings window
        self.withdraw()

    def open(self):
        # pop up profile settings window
        self.refresh()
        self.deiconify()
        self.lift()
