#!/usr/bin/env python3
#########################################
# 版本：1.5.1
# 更新时间：2021年10月06日
# Need: unix, python3-tk, python3-pip, pymouse, keyboard
#########################################
import os
import sys
import time
import json
import shutil
import keyboard
import traceback
import ttkthemes
import pyautogui
import threading
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
import tkinter.filedialog as filedialog
import Xlib.threaded as threaded
#import pymouse.unix as pymouse
########################
#
########################
def Inputt(key):
    if key.event_type == "up":
        global setting
        if setting:
            Setting(key)
        else:
            Mouse(key)
            #Mouse(key)

def Open():
    path = filedialog.askopenfilename(title="打开", filetypes=[["json 文件", "*.json"], ["全部文件", ["*.*"]]])
    if not path == "" or path == ():
        shutil.copy(path, get_home() + "/.config/uengine-keyboard/key.json")
        if messagebox.askyesno(title="提示", message="导入成功！是否现在重启程序以便生效？"):
            ReStartProgram()

def Save():
    path = filedialog.asksaveasfilename(title="打开", filetypes=[["json 文件", "*.json"], ["全部文件", ["*.*"]]])
    if not path == "" or path == ():
        shutil.copy(get_home() + "/.config/uengine-keyboard/key.json", path)
        messagebox.showinfo(title="提示", message="导出成功！")

# 重启本应用程序
def ReStartProgram()->"重启本应用程序":
    python = sys.executable
    os.execl(python, python, * sys.argv)


def Mouse(key):
    print(keybo)
    if keybo.__contains__(key.name):
        print(keybo[key.name]["MousePlace"])
        pyautogui.FAILSAFE = False
        #os.system(programPath + "/mouse.py {} {}".format(keybo[key.name]["MousePlace"][0], keybo[key.name]["MousePlace"][1]))
        pyautogui.click(keybo[key.name]["MousePlace"][0], keybo[key.name]["MousePlace"][1])
        #pyautogui.click(1500, 800)
        #m.click(keybo[key.name]["MousePlace"][0],keybo[key.name]["MousePlace"][1])

def Setting(key):
    if key.event_type == 'up':
        keybo[key.name] = {"Mouse": "Left", "MousePlace": pyautogui.position()}
        write_txt("{}/.config/uengine-keyboard/key.json".format(get_home()), json.dumps(keybo))
        global inputs
        inputs = True
        global setting
        setting = False
        return False

def ShowTips():
    try:
        if setting:
            settingLabelText.set('''设置方法：把鼠标移动带所需位置然后按下需要设置的按键即可（{}x{}）
提示：
1、目前不支持同时按两个及以上按键，只支持在单一时间内按一个按键;
2、使用映射不能关闭本窗口，但可以最小化;
3、本程序需要 root 权限才能使用;
4、映射时会占用鼠标，所以在使用时最好不要使用鼠标;'''.format(pyautogui.position()[0], pyautogui.position()[1]))
            settingButton.configure(state=tk.DISABLED)
        else:
            settingLabelText.set('''点击“设置”按钮设置映射（{}x{}）
提示：
1、目前不支持同时按两个及以上按键，只支持在单一时间内按一个按键;
2、使用映射不能关闭本窗口，但可以最小化;
3、本程序需要 root 权限才能使用;
4、映射时会占用鼠标，所以在使用时最好不要使用鼠标;'''.format(pyautogui.position()[0], pyautogui.position()[1]))
            settingButton.configure(state=tk.NORMAL) 
        time.sleep(0.1)
        ShowTips()
    except:
        traceback.print_exc()
        if not close:
            ShowTips()

def Closing():
    close = True
    window.destroy()

def Key():
    keyboard.hook(Inputt)

# 获取用户主目录
def get_home()->"获取用户主目录":
    return os.path.expanduser('~')

# 写入文本文档
def write_txt(path: "路径", things: "内容")->"写入文本文档": 
    file = open(path, 'w', encoding='UTF-8')  # 设置文件对象
    file.write(things)  # 写入文本
    file.close()  # 关闭文本对象

# 读取文本文档
def readtxt(path: "路径")->"读取文本文档":
    f = open(path, "r")  # 设置文件对象
    str = f.read()       # 获取内容
    f.close()            # 关闭文本对象
    return str           # 返回结果

def Settings():
    global setting
    setting = True

def Clean():
    if messagebox.askokcancel(title="提示", message="你确定要删除吗？"):
        shutil.rmtree("{}/.config/uengine-keyboard".format(get_home()))
        if messagebox.askyesno(title="提示", message="删除成功！是否现在重启程序以便生效？"):
            ReStartProgram()

def About():
    threading.Thread(target=os.system, args=["{}/uengine-runner-about".format(programPath)]).start()

###################
#
###################
if not os.path.exists("{}/.config/uengine-keyboard".format(get_home())):
    os.mkdir("{}/.config/uengine-keyboard".format(get_home()))
if not os.path.exists("{}/.config/uengine-keyboard/key.json".format(get_home())):
    write_txt("{}/.config/uengine-keyboard/key.json".format(get_home()), "{}")

###################
#
###################
setting = False
close = False
programPath = os.path.split(os.path.realpath(__file__))[0]  # 返回 string
iconPath = "{}/icon.png".format(os.path.split(os.path.realpath(__file__))[0])
keybo = json.loads(readtxt("{}/.config/uengine-keyboard/key.json".format(get_home())))
version = json.loads(readtxt("{}/information.json".format(programPath)))["Version"]

###################
# 判断是不是 root
###################
if os.geteuid() != 0:
    print("不是以 root 权限运行本程序！")
    root = tk.Tk()
    root.overrideredirect(1)
    root.withdraw()
    messagebox.showerror(title="错误", message="不是以 root 权限运行本程序！")
    sys.exit(1)

###################
#
###################
window = tk.Tk()
win = ttk.Frame(window)
show = ttk.Frame(win)

settingLabelText = tk.StringVar()

# 设置菜单栏
menu = tk.Menu(window, tearoff=0, background="white")  
programMenu = tk.Menu(menu, tearoff=0, background="white")
aboutMenu = tk.Menu(menu, tearoff=0, background="white")

settingLabel = ttk.Label(win, textvariable=settingLabelText)

settingMouseToKeyboard = ttk.Button(show, text="启动键盘映射（已启用）")
settingButton = ttk.Button(show, text="添加或覆盖键盘映射设置", command=Settings)

settingMouseToKeyboard.configure(state=tk.DISABLED)

style = ttkthemes.ThemedStyle(window)
style.set_theme("breeze")
window.protocol('WM_DELETE_WINDOW', Closing)
window.resizable(0, 0)
window.iconphoto(False, tk.PhotoImage(file=iconPath))
window.title("UEngine 键盘映射 {}".format(version))

menu.add_cascade(label="程序", menu=programMenu)
menu.add_cascade(label="帮助", menu=aboutMenu)
menu.configure(activebackground="dodgerblue")

programMenu.add_command(label="导入映射设置", command=Open)
programMenu.add_command(label="导出映射设置", command=Save)
programMenu.add_command(label="删除所有映射设置", command=Clean)
programMenu.add_separator()
programMenu.add_command(label="退出程序", command=sys.exit)
programMenu.configure(activebackground="dodgerblue")

aboutMenu.add_command(label="关于", command=About)

window.config(menu=menu)  # 显示菜单栏

show.grid(row=1, column=0)

settingLabel.grid(row=0, column=0)

settingMouseToKeyboard.grid(row=0, column=0)
settingButton.grid(row=0, column=1)

win.pack(fill="both", expand="yes")
#threaded.lock.allocate_lock()
threading.Thread(target=Key).start()
threading.Thread(target=ShowTips).start()
pyautogui.FAILSAFE = False
'''def B(key):
    if key.event_type == "up":
        print(pyautogui.position())
        print(key.name)
        pyautogui.click(1500, 800)
keyboard.hook(B)
keyboard.wait()'''
window.mainloop()