#coding: utf-8
import os,sys,json,io,traceback,time

#设定输出位utf8
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

panelPath = os.getenv('BT_PANEL')
if not panelPath:
    panelPath = "/www/server/panel"

os.chdir(panelPath)
class_dir = panelPath + "/class"
if not class_dir in sys.path:
    sys.path.insert(0, class_dir)

public_dir = panelPath + "/class/public"
if not public_dir in sys.path:
    sys.path.insert(0, public_dir)

def returnMsg(status, msg):
    """
    返回消息格式化
    """
    print("--PIPE_RES_START--")
    print(json.dumps({'status': status, 'msg': msg}))
    return

def returnData(res):
    """
    返回数据格式化
    """
    print("--PIPE_RES_START--")
    print(res)
    return

def get_error_info():
    """
    获取面板详细错误
    """
    errorMsg = traceback.format_exc()
    return errorMsg
    
try:    
    import public
except:
    returnMsg(False, get_error_info())
    sys.exit(0)

def delete_pyds():
    keys = ['pluginAuth','panelAuth','panelPlugin']
    for key in keys:
        py_filename = "{}/{}.py".format(class_dir, key)
        if not os.path.exists(py_filename): continue

        filename = "{}/{}.pyd".format(class_dir, key)
        if os.path.exists(filename):
            try:
                os.remove(filename)
            except:pass
            

def get_script_object(filename):

    _obj = sys.modules.get(filename, None)
    if _obj: return _obj
    from types import ModuleType
    _obj = sys.modules.setdefault(filename, ModuleType(filename))
    _code = public.readFile(filename)
    _code_object = compile(_code, filename, 'exec')
    _obj.__file__ = filename
    _obj.__package__ = ''
    exec(_code_object, _obj.__dict__)
    return _obj

class panelRun:

    def run(self, get):
        delete_pyds()
        if hasattr(get, 'module_name'):
            return self.module_run(get)
        return self.plugin_run(get)

    # 插件运行入口
    def plugin_run(self,get):
        
        if not hasattr(get, 'name'): 
            return public.returnMsg(False, public.lang('缺少必要参数:{}', ('name',)))
        if not hasattr(get, 's'):
            return public.returnMsg(False, public.lang('缺少必要参数:{}', ('s',)))

        action = get.s
        plugin_name = get.name

        is_import = False
        try:
            import PluginLoader      
            is_import = True     
        except:pass

        if is_import:    
            result = PluginLoader.plugin_run(plugin_name, action, get)      
        else:
            class_name = "{}_main".format(plugin_name)
            plugin_dir = "{}/plugin/{}".format(panelPath, plugin_name)
            plugin_main_file = "{}/{}.py".format(plugin_dir, class_name)

            if not os.path.exists(plugin_main_file):
                return public.returnMsg(False, public.lang('插件主文件不存在:{}', (plugin_main_file,)))

            plugin_body = public.readFile(plugin_main_file)
            if not "import" in plugin_body:
                return public.returnMsg(False, public.lang('插件主文件不是有效的Python脚本:{}', (plugin_name,)))

            def_object = get_script_object(plugin_main_file)
            if not hasattr(def_object, class_name):
                return public.returnMsg(False, public.lang('插件主类不存在:{}', (class_name,)))

            plugin_class = getattr(def_object, class_name)()
            if not hasattr(plugin_class, action):
                return public.returnMsg(False, public.lang('插件没有指定方法:{}', (action,)))

            func = getattr(plugin_class, action)
            if not callable(func):
                return public.returnMsg(False, public.lang('插件方法调用失败:{}', (action,)))
            result = func(get)
        return result
       

    # 模块运行入口
    def module_run(self,get):

        if not hasattr(get, 'module_name'):
            return public.returnMsg(False, public.lang('缺少必要参数:{}', ('module_name',)))

        if not hasattr(get, 'action'):
            return public.returnMsg(False, public.lang('缺少必要参数:{}', ('action',)))

        module_index = ""
        if hasattr(get, 'module_index'):
            module_index = get.module_index
        
        action = get.action
        module_name = get.module_name

        is_import = False
        try:
            import PluginLoader      
            is_import = True     
        except:pass
        
        if is_import:    
            result = PluginLoader.module_run(module_name, action, get)
        else:
            class_name = "main"
            if module_index == "mod":
                module_main_file = "{}/mod/project/{}Mod.py".format(panelPath, module_name)
            else:
                module_main_file = "{}/class/{}Model/{}Model.py".format(panelPath, module_name,module_name)
                if not os.path.exists(module_main_file):
                    module_main_file = "{}/class/projectModel/{}Model.py".format(panelPath,module_name)

            if not os.path.exists(module_main_file):
                return public.returnMsg(False, public.lang('模块主文件不存在:{}', (module_main_file,)))

            module_body = public.readFile(module_main_file)
            if not "import" in module_body:
                return public.returnMsg(False, public.lang('模块主文件不是有效的Python脚本:{}', (module_name,)))

            def_object = get_script_object(module_main_file)
            if not hasattr(def_object, class_name):
                return public.returnMsg(False, public.lang('模块主类不存在:{}', (class_name,)))

            module_class = getattr(def_object, class_name)()
            if not hasattr(module_class, action):
                return public.returnMsg(False, public.lang('模块没有指定方法:{}', (action,)))

            func = getattr(module_class, action)
            if not callable(func):
                return public.returnMsg(False, public.lang('模块方法调用失败:{}', (action,)))
            result = func(get)

        return result


if __name__ == "__main__":

    try: 
        input_data = sys.stdin.buffer.read().decode('utf-8')
        params = json.loads(input_data)
        get = public.to_dict_obj(params)

        mod_run = panelRun()
        res = mod_run.run(get)        
        if isinstance(res, (dict, list)):
            res = json.dumps(res)
        elif isinstance(res, bool):
            res = "true" if res else "false"
        elif isinstance(res, (int, float, str)):
            res = str(res)
        elif res is None:
            res = ""
			
        returnData(res)  
    except:
        returnMsg(False, get_error_info())
