#!/usr/bin/env python
#encoding=utf-8

try:
    # for Python2
    import tkMessageBox as messagebox
    import ttk
    from Tkinter import *
except ImportError:
    # for Python3
    try:
        from tkinter import *
        from tkinter import filedialog, messagebox, ttk
    except Exception as e:
        pass

import base64
import json
import os
import platform
import sys
import threading
import webbrowser

import util

CONST_APP_VERSION = "MaxBot (2024.04.18)"

CONST_MAXBOT_LAUNCHER_FILE = "config_launcher.json"
CONST_MAXBOT_CONFIG_FILE = "settings.json"

translate={}

URL_DONATE = 'https://max-everyday.com/about/#donate'
URL_HELP = 'https://max-everyday.com/2018/08/max-auto-reg-bot/'
URL_RELEASE = 'https://github.com/max32002/joint_bot/releases'
URL_FB = 'https://www.facebook.com/maxbot.ticket'
URL_CHROME_DRIVER = 'https://chromedriver.chromium.org/'
URL_FIREFOX_DRIVER = 'https://github.com/mozilla/geckodriver/releases'
URL_EDGE_DRIVER = 'https://developer.microsoft.com/zh-tw/microsoft-edge/tools/webdriver/'

def load_translate():
    translate = {
        'en_us': {
            "language": 'Language',
            "enable": 'Enable',
            "config_list": 'Config List',
            "advanced": 'Advanced',
            "about": 'About',
            "run": 'Run',
            "browse": 'Browse...',
            "save": 'Save',
            "exit": 'Close',
            "copy": 'Copy',
            "restore_defaults": 'Restore Defaults',
            "done": 'Done',
            "maxbot_slogan": 'MaxRegBot is a FREE and open source bot program. Wish you good luck.',
            "donate": 'Donate',
            "help": 'Help',
            "release": 'Release'
        },
        'zh_tw': {
            "language": '語言',
            "enable": '啟用',
            "config_list": '設定檔管理',
            "advanced": '進階設定',
            "autofill": '自動填表單',
            "about": '關於',
            "run": '搶票',
            "browse": '開啟...',
            "save": '存檔',
            "exit": '關閉',
            "copy": '複製',
            "restore_defaults": '恢復預設值',
            "done": '完成',
            "maxbot_slogan": 'MaxRegBot是一個免費、開放原始碼的搶票機器人。\n祝您掛號成功。',
            "donate": '打賞',
            "release": '所有可用版本',
            "help": '使用教學'
        },
        'zh_cn': {
            "language": '语言',
            "enable": '启用',
            "config_list": '设定档管理',
            "advanced": '進階設定',
            "autofill": '自动填表单',
            "about": '关于',
            "run": '抢票',
            "browse": '开启...',
            "save": '存档',
            "exit": '关闭',
            "copy": '复制',
            "restore_defaults": '恢复默认值',
            "done": '完成',
            "maxbot_slogan": 'MaxRegBot 是一个免费的开源机器人程序。\n祝您挂号成功。',
            "donate": '打赏',
            "help": '使用教学',
            "release": '所有可用版本'
        },
        'ja_jp': {
            "language": '言語',
            "enable": '有効',
            "config_list": 'Config List',
            "advanced": '高度な設定',
            "autofill": 'オートフィル',
            "about": '情報',
            "run": 'チケットを取る',
            "browse": '開ける...',
            "save": '保存',
            "exit": '閉じる',
            "copy": 'コピー',
            "restore_defaults": 'デフォルトに戻す',
            "done": '終わり',
            "maxbot_slogan": 'MaxRegBot は無料のオープン ソース ボット プログラムです。チケットの成功をお祈りします。',
            "donate": '寄付',
            "help": '利用方法',
            "release": 'リリース'
        }
    }
    return translate

def get_default_config():
    config_dict={}

    config_dict["list"] = [CONST_MAXBOT_CONFIG_FILE]

    config_dict["advanced"] = {}
    config_dict["advanced"]["language"] = "English"

    return config_dict

def load_json():
    app_root = util.get_app_root()
    config_filepath = os.path.join(app_root, CONST_MAXBOT_LAUNCHER_FILE)

    config_dict = None
    if os.path.isfile(config_filepath):
        with open(config_filepath) as json_data:
            config_dict = json.load(json_data)
    else:
        config_dict = get_default_config()
    return config_filepath, config_dict

def btn_restore_defaults_clicked(language_code):
    app_root = util.get_app_root()
    config_filepath = os.path.join(app_root, CONST_MAXBOT_LAUNCHER_FILE)
    if os.path.exists(str(config_filepath)):
        try:
            os.unlink(str(config_filepath))
        except Exception as exc:
            print(exc)
            pass

    config_dict = get_default_config()
    messagebox.showinfo(translate[language_code]["restore_defaults"], translate[language_code]["done"])

    global root
    load_GUI(root, config_dict)

def btn_save_clicked():
    btn_save_act()

def btn_save_act(slience_mode=True):
    app_root = util.get_app_root()
    config_filepath = os.path.join(app_root, CONST_MAXBOT_LAUNCHER_FILE)

    config_dict = get_default_config()
    language_code = get_language_code_by_name(config_dict["advanced"]["language"])

    config_dict["advanced"]["language"] = combo_language.get().strip()
    language_code = get_language_code_by_name(config_dict["advanced"]["language"])

    filelist = [txt_file_name[i].get().strip() for i in range(15)]
    config_dict["list"] = filelist

    util.save_json(config_dict, config_filepath)
    
    if not slience_mode:
        messagebox.showinfo(translate[language_code]["save"], translate[language_code]["done"])

    return True

def open_url(url):
    webbrowser.open_new(url)

def btn_exit_clicked():
    root.destroy()

def btn_donate_clicked():
    open_url.open(URL_DONATE)

def btn_help_clicked():
    open_url.open(URL_HELP)

def callbackLanguageOnChange(event):
    applyNewLanguage()

def get_language_code_by_name(new_language):
    language_code = "en_us"
    if '繁體中文' in new_language:
        language_code = 'zh_tw'
    if '簡体中文' in new_language:
        language_code = 'zh_cn'
    if '日本語' in new_language:
        language_code = 'ja_jp'
    return language_code

def applyNewLanguage():
    global combo_language
    new_language = combo_language.get().strip()
    #print("new language value:", new_language)

    language_code=get_language_code_by_name(new_language)

    global lbl_language

    lbl_language.config(text=translate[language_code]["language"])

    global tabControl

    tabControl.tab(0, text=translate[language_code]["config_list"])
    tabControl.tab(1, text=translate[language_code]["advanced"])
    tabControl.tab(2, text=translate[language_code]["about"])

    global lbl_slogan
    global lbl_help
    global lbl_donate
    global lbl_release

    lbl_slogan.config(text=translate[language_code]["maxbot_slogan"])
    lbl_help.config(text=translate[language_code]["help"])
    lbl_donate.config(text=translate[language_code]["donate"])
    lbl_release.config(text=translate[language_code]["release"])

    global btn_browse
    for i in range(15):
        btn_browse[i].config(text=translate[language_code]['browse'] + " " + str(i+1))

    global btn_run
    for i in range(15):
        btn_run[i].config(text=translate[language_code]['run'] + " " + str(i+1))

    global btn_save
    global btn_restore_defaults

    btn_save.config(text=translate[language_code]["save"])
    btn_restore_defaults.config(text=translate[language_code]["restore_defaults"])

def btn_items_browse_event(event):
    working_dir = os.path.dirname(os.path.realpath(__file__))
    btn_index = int(str(event.widget['text']).split(" ")[1])

    global widgets
    if "widgets" in globals():
        file_path = filedialog.askopenfilename(initialdir=working_dir, defaultextension=".json",filetypes=[("json Documents","*.json"),("All Files","*.*")])
        if not file_path is None:
            display_path = file_path
            if len(file_path) > len(working_dir):
                if file_path[:len(working_dir)]==working_dir:
                    display_path = file_path[len(working_dir)+1:]
            #print("json file path:", file_path)
            widgets['txt_file_name_value'][btn_index-1].set(display_path)
            #print("new json file path:", txt_file_name[btn_index-1].get().strip())

def btn_items_run_event(event):
    btn_index = int(str(event.widget['text']).split(" ")[1])

    global widgets
    if "widgets" in globals():
        filename=widgets['txt_file_name_value'][btn_index-1].get().strip()
        script_name = "chrome_tixcraft"
        threading.Thread(target=util.launch_maxbot, args=(script_name,filename,)).start()

def ConfigListTab(root, config_dict, language_code, UI_PADDING_X):
    frame_group_header = Frame(root)
    widgets = {
        'lbl_file_name': {},
        'txt_file_name': {},
        'txt_file_name_value': {},
        'btn_browse': {},
        'btn_run': {},
    }

    for i, filename in enumerate(config_dict["list"][:15]):
        widgets['lbl_file_name'][i] = Label(frame_group_header, text=str(i+1))
        widgets['lbl_file_name'][i].grid(column=0, row=i, sticky=E)

        widgets['txt_file_name_value'][i] = StringVar(frame_group_header, value=filename)
        widgets['txt_file_name'][i] = Entry(frame_group_header, width=20, textvariable=widgets['txt_file_name_value'][i])
        widgets['txt_file_name'][i].grid(column=1, row=i, sticky=W)

        widgets['btn_browse'][i] = ttk.Button(frame_group_header, text=translate[language_code]['browse'] + " " + str(i+1))
        widgets['btn_browse'][i].grid(column=2, row=i, sticky=W)
        widgets['btn_browse'][i].bind('<Button-1>', btn_items_browse_event)

        widgets['btn_run'][i] = ttk.Button(frame_group_header, text=translate[language_code]['run'] + " " + str(i+1))
        widgets['btn_run'][i].grid(column=3, row=i, sticky=W)
        widgets['btn_run'][i].bind('<Button-1>', btn_items_run_event)

    frame_group_header.grid(column=0, row=0, sticky=W, padx=UI_PADDING_X)
    return widgets


def AboutTab(root, language_code):
    row_count = 0

    frame_group_header = Frame(root)
    group_row_count = 0

    logo_filename = "maxbot_logo2_single.ppm"
    logo_img = PhotoImage(file=logo_filename)

    lbl_logo = Label(frame_group_header, image=logo_img)
    lbl_logo.image = logo_img
    lbl_logo.grid(column=0, row=group_row_count, columnspan=2)

    group_row_count +=1

    global lbl_slogan
    global lbl_help
    global lbl_donate
    global lbl_release

    lbl_slogan = Label(frame_group_header, text=translate[language_code]['maxbot_slogan'], wraplength=400, justify="center")
    lbl_slogan.grid(column=0, row=group_row_count, columnspan=2)

    group_row_count +=1

    lbl_help = Label(frame_group_header, text=translate[language_code]['help'])
    lbl_help.grid(column=0, row=group_row_count, sticky = E)

    lbl_help_url = Label(frame_group_header, text=URL_HELP, fg="blue", cursor="hand2")
    lbl_help_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_help_url.bind("<Button-1>", lambda e: open_url(URL_HELP))

    group_row_count +=1

    lbl_donate = Label(frame_group_header, text=translate[language_code]['donate'])
    lbl_donate.grid(column=0, row=group_row_count, sticky = E)

    lbl_donate_url = Label(frame_group_header, text=URL_DONATE, fg="blue", cursor="hand2")
    lbl_donate_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_donate_url.bind("<Button-1>", lambda e: open_url(URL_DONATE))

    group_row_count +=1

    lbl_release = Label(frame_group_header, text=translate[language_code]['release'])
    lbl_release.grid(column=0, row=group_row_count, sticky = E)

    lbl_release_url = Label(frame_group_header, text=URL_RELEASE, fg="blue", cursor="hand2")
    lbl_release_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_release_url.bind("<Button-1>", lambda e: open_url(URL_RELEASE))

    group_row_count +=1

    lbl_fb_fans = Label(frame_group_header, text=u'Facebook')
    lbl_fb_fans.grid(column=0, row=group_row_count, sticky = E)

    lbl_fb_fans_url = Label(frame_group_header, text=URL_FB, fg="blue", cursor="hand2")
    lbl_fb_fans_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_fb_fans_url.bind("<Button-1>", lambda e: open_url(URL_FB))


    group_row_count +=1

    lbl_chrome_driver = Label(frame_group_header, text=u'Chrome Driver')
    lbl_chrome_driver.grid(column=0, row=group_row_count, sticky = E)

    lbl_chrome_driver_url = Label(frame_group_header, text=URL_CHROME_DRIVER, fg="blue", cursor="hand2")
    lbl_chrome_driver_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_chrome_driver_url.bind("<Button-1>", lambda e: open_url(URL_CHROME_DRIVER))

    group_row_count +=1

    lbl_firefox_driver = Label(frame_group_header, text=u'Firefox Driver')
    lbl_firefox_driver.grid(column=0, row=group_row_count, sticky = E)

    lbl_firefox_driver_url = Label(frame_group_header, text=URL_FIREFOX_DRIVER, fg="blue", cursor="hand2")
    lbl_firefox_driver_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_firefox_driver_url.bind("<Button-1>", lambda e: open_url(URL_FIREFOX_DRIVER))

    group_row_count +=1

    lbl_edge_driver = Label(frame_group_header, text=u'Edge Driver')
    lbl_edge_driver.grid(column=0, row=group_row_count, sticky = E)

    lbl_edge_driver_url = Label(frame_group_header, text=URL_EDGE_DRIVER, fg="blue", cursor="hand2")
    lbl_edge_driver_url.grid(column=1, row=group_row_count, sticky = W)
    lbl_edge_driver_url.bind("<Button-1>", lambda e: open_url(URL_EDGE_DRIVER))

    frame_group_header.grid(column=0, row=row_count)

def AdvancedTab(root, config_dict, language_code, UI_PADDING_X):
    row_count = 0

    frame_group_header = Frame(root)
    group_row_count = 0

    # for kktix
    print("==[advanced]==")
    print(config_dict["advanced"])

    global lbl_language
    lbl_language = Label(frame_group_header, text=translate[language_code]['language'])
    lbl_language.grid(column=0, row=group_row_count, sticky = E)

    global combo_language
    combo_language = ttk.Combobox(frame_group_header, state="readonly")
    combo_language['values']= ("English","繁體中文","簡体中文","日本語")
    combo_language.set(config_dict["advanced"]['language'])
    combo_language.bind("<<ComboboxSelected>>", callbackLanguageOnChange)
    combo_language.grid(column=1, row=group_row_count, sticky = W)

    frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X)


def get_action_bar(root, language_code):
    frame_action = Frame(root)

    global btn_save
    global btn_restore_defaults

    btn_save = ttk.Button(frame_action, text=translate[language_code]['save'], command= lambda: btn_save_clicked() )
    btn_save.grid(column=1, row=0)

    btn_restore_defaults = ttk.Button(frame_action, text=translate[language_code]['restore_defaults'], command= lambda: btn_restore_defaults_clicked(language_code))
    btn_restore_defaults.grid(column=2, row=0)

    return frame_action

def clearFrame(frame):
    # destroy all widgets from frame
    for widget in frame.winfo_children():
       widget.destroy()

def load_GUI(root, config_dict):
    clearFrame(root)

    #language_code="en_us"
    language_code = get_language_code_by_name(config_dict["advanced"]["language"])

    row_count = 0

    global tabControl
    tabControl = ttk.Notebook(root)
    tab1 = Frame(tabControl)
    tabControl.add(tab1, text=translate[language_code]['config_list'])

    tab2 = Frame(tabControl)
    tabControl.add(tab2, text=translate[language_code]['advanced'])

    tab3 = Frame(tabControl)
    tabControl.add(tab3, text=translate[language_code]['about'])
    tabControl.grid(column=0, row=row_count)
    tabControl.select(tab1)

    row_count+=1

    frame_action = get_action_bar(root, language_code)
    frame_action.grid(column=0, row=row_count)

    global UI_PADDING_X
    widgets = ConfigListTab(tab1, config_dict, language_code, UI_PADDING_X)
    AdvancedTab(tab2, config_dict, language_code, UI_PADDING_X)
    AboutTab(tab3, language_code)
    return widgets

def main_gui():
    global translate
    # only need to load translate once.
    translate = load_translate()

    global config_filepath
    global config_dict
    # only need to load json file once.
    config_filepath, config_dict = load_json()

    global root
    root = Tk()
    root.title(CONST_APP_VERSION)

    global UI_PADDING_X
    UI_PADDING_X = 15

    global widgets
    widgets = load_GUI(root, config_dict)

    GUI_SIZE_WIDTH = 580
    GUI_SIZE_HEIGHT = 580

    GUI_SIZE_MACOS = str(GUI_SIZE_WIDTH) + 'x' + str(GUI_SIZE_HEIGHT)
    GUI_SIZE_WINDOWS=str(GUI_SIZE_WIDTH-60) + 'x' + str(GUI_SIZE_HEIGHT-55)

    GUI_SIZE =GUI_SIZE_MACOS

    if platform.system() == 'Windows':
        GUI_SIZE = GUI_SIZE_WINDOWS

    root.geometry(GUI_SIZE)

    # for icon.
    icon_filepath = 'tmp.ico'

    # icon format.
    iconImg = '[encoded data, 17428 characters]'
    if platform.system() == 'Linux':
        # PNG format.
        iconImg = '[encoded data, 15932 characters]'

    tmpIcon = open(icon_filepath, 'wb+')
    tmpIcon.write(base64.b64decode(iconImg))
    tmpIcon.close()
    if platform.system() == 'Windows':
        root.iconbitmap(icon_filepath)
    if platform.system() == 'Linux':
        logo = PhotoImage(file=icon_filepath)
        root.call('wm', 'iconphoto', root._w, logo)
    os.remove(icon_filepath)

    root.mainloop()

if __name__ == "__main__":
    main_gui()
