import os
import sys
import getopt
import shutil
import configparser
import PySimpleGUI as sg

iniFilePath = os.path.join(os.getcwd(), "config.ini")
conf = configparser.ConfigParser()
conf.read(iniFilePath)

current_dir = os.getcwd()
project_dir = os.path.dirname(current_dir)

def init_dirs():
    new_dirs = [
        os.path.join(project_dir, "wwwroot"),
        os.path.join(project_dir, "wwwroot", "kxpms"),
        os.path.join(project_dir, "wwwroot", "kxpms", conf.get('uploads', 'upload_dir')),
        os.path.join(project_dir, "wwwroot", "kxpms", conf.get('uploads', 'netdisc'))
    ]

    for d in new_dirs:
        if not os.path.exists(d):
            os.mkdir(d)

def update_app_config():
    upload_path = os.path.join(project_dir, "wwwroot", "kxpms")
    temp = os.path.join(os.getcwd(), "config1.ini")
    # fd = open(temp, mode="w", encoding="utf-8")
    # fd.close()
    shutil.copy(iniFilePath, temp)
    cp2 = configparser.ConfigParser()
    cp2.read(temp)
    sections = conf.sections()

    for section in sections:
        for item in conf.items(section):
            cp2.set(section, item[0], item[1])

    cp2.set("uploads", "upload_path", upload_path)

    with open(temp, "w+") as f:
        cp2.write(f)

    shutil.move(temp, iniFilePath)
    # os.remove(temp)
    conf.read(iniFilePath)

def update_nginx_conf():
    source_file = os.path.join(current_dir, "nginx.conf.template")
    target_file = os.path.join(project_dir, "nginx-1.18.0", "conf", "nginx.conf")

    if os.path.exists(target_file):
        os.remove(target_file)

    with open(source_file, 'r', encoding="utf8") as src, open(target_file, 'w', encoding="utf8") as dst:
        lines = src.readlines()
        for content in lines:
            if content.find("        listen       80;") != -1:
                dst.write("        listen       {};\n".format(conf.get('uploads', 'port') or 80))
            elif content.find("        server_name  localhost;") != -1:
                dst.write("        server_name  {};\n".format(conf.get('uploads', 'host') or "localhost"))
            elif content.find("            root   html;") != -1:
                dst.write("            root   {};\n".format(os.getcwd()))
            else:
                dst.write(content)
    print(target_file, source_file)
    # shutil.move(source_file, target_file)

def install_nssm(app_name, app_path):
    return os.system("nssm.exe install {} {}".format(app_name, app_path))

# http://nssm.cc/usage
def manage_nssm_service(app_name, cmd):
    '''
        nssm start <servicename> 启动服务
        nssm stop <servicename> 停止服务
        nssm restart <servicename> 重启服务
        nssm remove <servicename> 删除服务,需要确认
        nssm remove <servicename> confirm 删除服务,无需确认
        nssm status <servicename>
        nssm statuscode <servicename>
        nssm rotate <servicename> 服务日志文件滚动
        nssm processes <servicename>
    '''
    services = ['start', 'stop', 'restart', 'remove', 'status', 'processes']
    if cmd not in services:
        return False
    return os.system("nssm.exe {} {}".format(cmd, app_name))

def exec_nssm_env_cmd(app_name, param_dict = {}):
    '''
        nssm set <servicename> AppParameters -jar slave.jar -secret redacted 服务启动时携带的参数
        nssm set <servicename> AppDirectory C:\\Jenkins 服务启动的文件路径 
        nssm set <servicename> AppStdout C:\\Jenkins\\jenkins.log 服务标准日志输出
        nssm set <servicename> AppStderr C:\\Jenkins\\jenkins.log 服务错误日志输出
        nssm set <servicename> AppStopMethodSkip 0  在崩溃后或服务正常停止时清理应用程序时使用的各种停止方法和超时
        nssm set <servicename> AppStopMethodConsole 1000
        nssm set <servicename> AppThrottle 5000 如果app运行时间少于5秒,延迟启动
    '''
    for key, value in param_dict.items():
        res = os.system("nssm.exe set {} {} {}".format(app_name, key, value))
        print(res)

def start_nginx_service():
    '''
        ./nginx 启动
        ./nginx -s stop 停止
        ./nginx -s quit 退出
        ./nginx -s reload 重载
    '''
    nginx_dir = os.path.join(project_dir, "nginx-1.18.0", "nginx.exe")
    res = install_nssm(conf.get('application', 'nginx'), nginx_dir)
    print(res)
    # exec_nssm_env_cmd(conf.get('application', 'nginx'), {
    #     'AppParameters': '-s start'
    # })
    res = manage_nssm_service(conf.get('application', 'nginx'), "start")
    print(res)

def start_app_service():
    app_dir = os.path.join(current_dir, "start.exe")
    res = install_nssm(conf.get('application', 'name'), app_dir)
    print(res)
    exec_nssm_env_cmd(conf.get('application', 'name'), {
        'AppThrottle': '5000'
    })
    res = manage_nssm_service(conf.get('application', 'name'), "start")
    print(res)

def start_service():
    start_nginx_service()
    start_app_service()

def stop_app_service():
    app_dir = os.path.join(current_dir, "start.exe")
    res = install_nssm(conf.get('application', 'name'), app_dir)
    print(res)
    exec_nssm_env_cmd(conf.get('application', 'name'), {
        'AppThrottle': '5000'
    })
    res = manage_nssm_service(conf.get('application', 'name'), "stop")
    print(res)

def stop_nginx_service():
    nginx_dir = os.path.join(project_dir, "nginx-1.18.0", "nginx.exe")
    res = install_nssm(conf.get('application', 'nginx'), nginx_dir)
    print(res)
    res = manage_nssm_service(conf.get('application', 'nginx'), "start")
    print(res)

def stop_service():
    stop_app_service()
    stop_nginx_service()

def set_nssm_env():
    if sys.platform == 'win32':
        os.chdir(current_dir)
        start_service()
    else:
        # res = os.system("ls -a")
        # print(res)
        print("暂不支持在非windows平台部署")

def user_command(argv):
    flag = False
    value = None
    opts, args = getopt.getopt(argv[1:], "a:c:h", ["app=", "cmd=", "help"])
    for opt_name, opt_value in opts:
        if opt_name in ('-h','--help'):
            print('''
usage:
    nssm start <servicename> 启动服务
    nssm stop <servicename> 停止服务
    nssm restart <servicename> 重启服务
    nssm remove <servicename> 删除服务,需要确认
    nssm remove <servicename> confirm 删除服务,无需确认
    nssm status <servicename>
    nssm statuscode <servicename>
    nssm rotate <servicename> 服务日志文件滚动
    nssm processes <servicename>
            ''')
            sys.exit()
        if opt_name in ('-a','--app'):
            if flag == False:
                flag = True
                value = opt_value
            else:
                res = manage_nssm_service(opt_value, value)
                if res: print(res)
                else: print("[*] unsupport command")
        if opt_name in ('-c','--cmd'):
            if flag == False:
                flag = True
                value = opt_value
            else:
                res = manage_nssm_service(value, opt_value)
                if res: print(res)
                else: print("[*] unsupport command")
    print(argv)

# =======================GUI==========================
start_text = "启动应用"
stop_text = "关闭应用"
restart_text = "重启应用"

start_btn = sg.Button(start_text, button_color=('white', 'springgreen4'))
stop_btn = sg.Button(stop_text, button_color=('white', 'firebrick3'))
restart_btn = sg.Button(restart_text)

layout = [
    [start_btn, stop_btn, restart_btn]
]

# Create the Window
window = sg.Window('KXPMS项目管理系统', layout, auto_size_buttons=False, default_button_element_size=(15, 3))

def start_project():
    update_app_config()
    init_dirs()
    update_nginx_conf()
    set_nssm_env()

def stop_project():
    stop_service()

def run():
    # Create the event loop
    while True:
        event, values = window.read()
        if event in (None, start_text): # User closed the Window or hit the Cancel button
            start_project()
        elif event in (None, stop_text):
            stop_project()
        elif event in (None, restart_text):
            stop_project()
            start_project()
        else:
            continue

        if event == sg.WIN_CLOSED:
            break

        print(f'Event: {event}')
    
    window.close()

def main(argv):
    if len(argv) > 1:
        user_command(argv)
    else:
        update_app_config()
        init_dirs()
        update_nginx_conf()
        set_nssm_env()

if __name__ == "__main__":
    # main(sys.argv)
    run()