"""
VN Scene Script Ext - game util
by Countd360
Provide functions to support game play

contents:
gskin, gskin_setattr, 
gpersdata_save, gpersdata_load, gpersdata_clear, 
gpersdata_to_brvars, brvars_to_gpersdata,


Function: gskin - switch game skin to 'skinname'
Syntax:
    gskin:skinname
Examples:
    gskin:skin_btnonly


Function: gskin_setattr - change skin attrubite 'pname' to 'pval'
Syntax:
    gskin_setattr:pname::pval
Examples:
    gskin_setattr:maxButtonsInSet::3


Function: gpersdata_save - save gpersdata to file 'Gpdata/[fname].dat'. If dst scene setted, goto dst scene when [next] clicked.
Syntax:
    gpersdata_save:fname:[normal next]:[error next]
Examples:
    gpersdata_save:mygame
    gpersdata_save:mygame:103
    gpersdata_save:mygame::104
    gpersdata_save:mygame:103:104


Function: gpersdata_load - load gpersdata from file 'Gpdata/[fname].dat'. If dst scene setted, goto dst scene when [next] clicked.
Syntax:
    gpersdata_load:fname:[normal next]:[error next]
Examples:
    gpersdata_load:mygame
    gpersdata_load:mygame:103
    gpersdata_load:mygame::104
    gpersdata_load:mygame:103:104


Function: gpersdata_clear - clear all var in gpersdata and delete gpersdata file 'Gpdata/[fname].dat'.
Syntax:
    gpersdata_clear:fname
Examples:
    gpersdata_clear:mygame


Function: gpersdata_to_brvars - load gpersdata to brVars(blackrain ext), if var name list not set load all in gpersdata
Syntax:
    gpersdata_to_brvars:[var name list, split by comma]
Examples:
    gpersdata_to_brvars
    gpersdata_to_brvars:var1,var2,var3


Function: brvars_to_gpersdata - load brVars(blackrain ext) to gpersdata, if var name list not set load all in brVars
Syntax:
    brvars_to_gpersdata:[var name list, split by comma]
Examples:
    brvars_to_gpersdata
    brvars_to_gpersdata:var1,var2,var3

Function: addvnssbtn - Add a button, which run a vnss cmd
Syntax:
    brvars_to_gpersdata:button text:[goto]:VNSS cmd
Examples:
    addvnssbtn:HideUIBtn::hideui        - add 'HideUIBtn' button, which run hideui cmd and stay in current cam
    addvnssbnt:ShowUIBtn:next:showui    - add 'ShowUIBtn' button, which run showui cmd and go to next cam

Function: switchactor - switch two actor's in runtime
Syntax:
    switchactor:act_id1:act_id2:[status]
Examples:
    switchactor:act0:act1                       - switch actor only, keep status
    switchactor:act0:act1:full                  - switch actor and all status
    switchactor:act0:act1:move_to,rotate_to     - switch actor and only 'move_to' and 'rotate_to' status

Function: loadfilerun - load another file and run vnss
Syntax:
    loadfilerun:filename
Examples:
    loadfilerun:nextscene.png   - load "nextscene.png" in the same folder of current png, and run VNSS

"""

from vnscenescript import statestr_to_int, run_state, run_action

def custom_action(game, act):
    """:type game: vngameengine.VNNeoController"""

    if act["action"] == "gskin":
        try:
            # save current skin's end button setting
            cskin = game.skin_get_current()
            if hasattr(cskin, "isEndButton") and hasattr(cskin, "endButtonTxt") and hasattr(cskin, "endButtonCall"):
                isEndButton = cskin.isEndButton
                endButtonTxt = cskin.endButtonTxt
                endButtonCall = cskin.endButtonCall
            else:
                isEndButton = None
            
            # change skin
            sname = act["actionparam"]
            game.skin_set_byname(sname)

            # restore end button setting
            if isEndButton:
                cskin = game.skin_get_current()
                cskin.isEndButton = isEndButton
                cskin.endButtonTxt = endButtonTxt
                cskin.endButtonCall = endButtonCall

            return True
        except Exception as e:
            print("action error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "gskin_setattr":
        try:
            pname = act["actionparam"]
            pval = eval(act["actionparam3"])
            # save current skin's end button setting
            cskin = game.skin_get_current()
            setattr(cskin, pname, pval)

            return True
        except Exception as e:
            print("gskin_setattr error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "gpersdata_save":
        try:
            fname = act["actionparam"]
            if act.has_key("actionparam2") and len(act["actionparam2"]) > 0:
                ndst = act["actionparam2"]
            else:
                ndst = None
            if act.has_key("actionparam3") and len(act["actionparam3"]) > 0:
                edst = act["actionparam3"]
            else:
                edst = None

            # save current gpersdata
            result = game.gpersdata_save(fname)
            if result:
                if ndst:
                    game.scenedata.scNextState = statestr_to_int(game, ndst)
            else:
                if edst:
                    game.scenedata.scNextState = statestr_to_int(game, edst)

            return True
        except Exception as e:
            print("gpersdata_save error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "gpersdata_load":
        try:
            fname = act["actionparam"]
            if act.has_key("actionparam2") and len(act["actionparam2"]) > 0:
                ndst = act["actionparam2"]
            else:
                ndst = None
            if act.has_key("actionparam3") and len(act["actionparam3"]) > 0:
                edst = act["actionparam3"]
            else:
                edst = None

            # load gpersdata
            result = game.gpersdata_load(fname)
            if result:
                if ndst:
                    game.scenedata.scNextState = statestr_to_int(game, ndst)
            else:
                if edst:
                    game.scenedata.scNextState = statestr_to_int(game, edst)

            return True
        except Exception as e:
            print("gpersdata_load error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "gpersdata_clear":
        try:
            fname = act["actionparam"]

            # clear gpersdata
            game.gpersdata_clear(fname)

            return True
        except Exception as e:
            print("gpersdata_clear error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "gpersdata_to_brvars":
        try:
            if act.has_key("actionparam") and len(act["actionparam"]) > 0:
                varnames = [s.strip() for s in act["actionparam"].split(",")]
            else:
                varnames = None

            # load gpersdata data to brVars
            for vname in game.gpersdata.keys():
                if varnames == None or vname in varnames:
                    if not hasattr(game.gdata, 'brVars'):
                        game.gdata.brVars = {}
                    game.gdata.brVars[vname] = game.gpersdata[vname]
                    print("gpersdata_to_brvars: %s = %s"%(vname, str(game.gpersdata[vname])))

            return True
        except Exception as e:
            print("gpersdata_to_brvars error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "brvars_to_gpersdata":
        try:
            if act.has_key("actionparam") and len(act["actionparam"]) > 0:
                varnames = [s.strip() for s in act["actionparam"].split(",")]
            else:
                varnames = None

            # load brVars to gpersdata data
            if not hasattr(game.gdata, 'brVars'):
                print("brVars not found! Set some vars first!")
                return True
            for vname in game.gdata.brVars.keys():
                if varnames == None or vname in varnames:
                    game.gpersdata[vname] = game.gdata.brVars[vname]
                    print("brvars_to_gpersdata: %s = %s"%(vname, str(game.gpersdata[vname])))

            return True
        except Exception as e:
            print("brvars_to_gpersdata error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "addvnssbtn":
        try:
            def parse_subact(txt):
                ar = txt.split(":", 3)
                sact = {}
                # act["arcode"] = ar
                sact["origintext"] = txt
                sact["states"] = act["states"]
                sact["action"] = ar[0]
                if len(ar) > 1:
                    sact["actionparam"] = ar[1]
                    if len(ar) > 2:
                        sact["actionparam2"] = ar[2]
                        if len(ar) > 3:
                            sact["actionparam3"] = ar[3]
                return sact
            def run_vnss_action(g, p):
                subact = p[0]
                gonext = p[1]
                res = run_action(g, subact)
                if res and gonext != None:
                    run_state(g, gonext, True)

            btntxt = act["actionparam"]
            if len(act["actionparam2"]) > 0:
                gonext = statestr_to_int(game, act["actionparam2"])
            else:
                gonext = None
            subact = parse_subact(act["actionparam3"])
            game.scenedata.scACustomButtons.append(btntxt)
            game.scenedata.scACustomButtons.append((run_vnss_action, (subact, gonext)))

            return True
        except Exception as e:
            print("addvnssbtn error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "switchactor":
        try:
            aid1 = act["actionparam"]
            aid2 = act["actionparam2"]
            if aid1 not in game._scenef_actors:
                raise Exception("Actor id <%s> is not registed!"%aid1)
            if aid2 not in game._scenef_actors:
                raise Exception("Actor id <%s> is not registed!"%aid2)
            if act.has_key("actionparam3") and len(act["actionparam3"]) > 0:
                option = act["actionparam3"]
                oldstates1 = game._scenef_actors[aid1].export_full_status()
                oldstates2 = game._scenef_actors[aid2].export_full_status()
                # change status
                if option != "full":
                    kss = set()
                    tss = option.split(",")
                    for ts in tss:
                        if ts in oldstates1 and ts in oldstates2:
                            kss.add(ts)
                    for tk in oldstates1.keys():
                        if tk not in kss:
                            del oldstates1[tk]
                    for tk in oldstates2.keys():
                        if tk not in kss:
                            del oldstates2[tk]
                game._scenef_actors[aid1].import_status(oldstates2)
                game._scenef_actors[aid2].import_status(oldstates1)
            # do switch actor id
            game._scenef_actors[aid1], game._scenef_actors[aid2] = game._scenef_actors[aid2], game._scenef_actors[aid1]
            # do switch name
            if aid1 in game.registeredChars and aid2 in game.registeredChars:
                game.registeredChars[aid1], game.registeredChars[aid2] = game.registeredChars[aid2], game.registeredChars[aid1]
            return True
        except Exception as e:
            print("switchactor error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

    if act["action"] == "loadfilerun":
        try:
            from os import path
            curscenedir = path.split(path.abspath(game.lastSceneLoadedFile))[0]
            filename = path.join(curscenedir, act["actionparam"])
            if not path.isfile(filename):
                print("[gameutil/loadfilerun ERROR] File not found!", filename)
                return True

            game.visible = False    # hide ui before loading
            game.event_unreg_listener("scene_loaded_after", hook_loadfilerun_loaded, "gameutil_loadfilerun_sceneload")
            game.event_reg_listener("scene_loaded_after", hook_loadfilerun_loaded, "gameutil_loadfilerun_sceneload")
            game.load_scene(filename)
            return True
        except Exception as e:
            print("loadfilerun error, can't parse command '%s': %s"%(act["origintext"], str(e)))
            return True

def debug_buttons(game,state):
    return [] # if we want no additional buttons

    # return in format of set_buttons_alt
    #return ["Demo btn (keitaro10)", demo1]

def hook_loadfilerun_loaded(game, evid, u_param):
    # show up ui again
    game.visible = True
    # unreg itself
    game.event_unreg_listener("scene_loaded_after", hook_loadfilerun_loaded, "gameutil_loadfilerun_sceneload")
    # start vnss
    print("New file '%s' is loaded. Lets go."%u_param)
    from vnscenescript import start_cur_view
    start_cur_view(game)


