Code style

Code style

global __vimLastAction

; 初始化class_Vim
vim_Init:
    #UseHook
    SetKeyDelay, -1
return

; 用于热键映射
vim_Key:
    vim.Key()
return

; 用于热键超时
vim_TimeOut:
    vim.IsTimeOut()
return

; 用于Count计数
Internal:
    __v.SetPlugin("Internal", "Array", "0.1", "内置插件")
    __v.SetAction("<1>", "数字 1")
    __v.SetAction("<2>", "数字 2")
    __v.SetAction("<3>", "数字 3")
    __v.SetAction("<4>", "数字 4")
    __v.SetAction("<5>", "数字 5")
    __v.SetAction("<6>", "数字 6")
    __v.SetAction("<7>", "数字 7")
    __v.SetAction("<8>", "数字 8")
    __v.SetAction("<9>", "数字 9")
    __v.SetAction("<0>", "数字 0")
    __v.SetAction("<>", "空操作")
    __v.SetAction("<Pass>", "空操作")
    __v.SetAction("<Default>", "恢复默认")
    __v := ""
return

<1>:
<2>:
<3>:
<4>:
<5>:
<6>:
<7>:
<8>:
<9>:
<0>:
<>:
<Pass>:
<Default>:
return

Class_vim()
{
    global __v
    GoSub, vim_Init
    __v := v := new __vim
    __v.LoadPlugin("Internal")
    return v
}

GetLastAction()
{
    return __vimLastAction
}

ShowInfo()
{
    Global vim
    obj := vim.GetMore(true)
    winObj := vim.GetWin(vim.LastFoundWin)
    if winObj.Count
        np .= winObj.Count
    Loop, % obj.MaxIndex()
    {
        act := vim.GetAction(obj[A_Index]["Action"])

        ; Type = 1 : Function
        if (act.Type = 1)
        {
            ActionDescList := act.Comment
            Key := obj[A_Index]["key"]
            np .= Key "`t" %ActionDescList%[Key] "`n"
        }
        else
        {
            np .= obj[A_Index]["key"] "`t" act.Comment "`n"
        }

        if (A_Index = 1)
            np .= "=====================`n"
    }
    MouseGetPos, posx, posy, A
    posx += 40
    posy += 40
    Tooltip, %np%, %posx%, %posy%
}

HideInfo()
{
    ; 当屏幕有非快捷键补全帮助信息时，不清理
    Global showToolTipStatus
    if (!showToolTipStatus)
    {
        Tooltip
    }
}

; 定义数据结构
; Class __vim {{{1
Class __vim
{
    __new()
    {
        this.PluginList := []
        this.WinList    := []
        this.WinInfo    := []
        this.ActionList := []
        this.ActionFromPlugin := []
        this.ExcludeWinList := []
        this.winGlobal  := new __win
        this.ErrorCode  := 0
        tihs.ActionFromPluginName := ""
        this.LastFoundWin := ""
    }

    ; LoadPlugin(PluginName) {{{2
    ; 用于注册插件
    LoadPlugin(PluginName)
    {
        if this.PluginList[PluginName]
            return this.PluginList[PluginName]
        p := new __Plugin(PluginName)
        this.PluginList[PluginName] := p
        back := this.ActionFromPluginName
        this.ActionFromPluginName := PluginName
        p.CheckSub()
        if p.Error
        {
            MsgBox load plugin "%PluginName%" error
            this.ActionFromPluginName := back
        }
    }

    ; SetPlugin(PluginName, Author = "", Ver = "", Comment = "") {{{2
    ; 设置Plugin信息
    SetPlugin(PluginName, Author = "", Ver = "", Comment = "")
    {
        p := this.PluginList[PluginName]
        p.Author := Author
        p.Ver := Ver
        p.Comment := Comment
    }

    ; GetPlugin(PluginName) {{{2
    ; 获取Plugin信息
    GetPlugin(PluginName)
    {
        return this.PluginList[PluginName]
    }

    ; Comment(Action, Desc, Complex = 1) {{{2
    ; 兼容老版本的vimcore.ahk
    Comment(Action, Desc = "", Complex = 1)
    {
        act := this.SetAction(Action, Desc)
        if not complex ; 不允许多次运行
            act.SetMaxTimes(1)
        return act
    }

    ; SetAction(Name, Comment) {{{2
    ; 用于为Action(动作)进行注释
    SetAction(Name, Comment = "")
    {
        if this.ActionList[Name]
            ra := This.ActionList[Name]
        else
            ra := This.ActionList[Name] := new __Action(Name, Comment)
        This.ActionFromPlugin[Name] := this.ActionFromPluginName
        return ra
    }

    ; GetAction(Name) {{{2
    ; 获取Action的信息
    GetAction(Name)
    {
        return this.ActionList[Name]
    }

    ; SetWin(winName, class, filepath, title) {{{2
    ; 添加win成员
    SetWin(winName, class, filepath = "", title = "")
    {
        if this.WinList[winName]
            rw := this.WinList[winName]
        else
            rw := this.WinList[winName] := new __win(class, filepath, title)
        this.WinInfo["class`t"class]       := winName
        this.WinInfo["filepath`t"filepath] := winName
        this.WinInfo["title`t"title]       := winName
        return rw
    }

    ; GetWin(winName) {{{2
    GetWin(winName = "")
    {
        if strlen(winName)
            return this.WinList[winName]
        else
            return this.winGlobal
    }

    ; CheckWin() {{{2
    CheckWin()
    {
        /*
        WinGetTitle, t, A
        if Strlen(winName := this.WinInfo["title`t"t])
            return winName
        */

        WinGet, f, ProcessName, A
        if Strlen(winName := this.WinInfo["filepath`t"f])
            return winName
        WinGetClass, c, A
        if Strlen(winName := this.WinInfo["class`t"c])
            return winName
    }

    ; mode(mode, win = "") {{{2
    ; 兼容老版本的vimcore.ahk
    mode(mode, win = "")
    {
        if not IsObject(this.GetWin(win))
            this.SetWin(win, win)
        return this.SetMode(mode, win)
    }

    ; SetMode(modeName, winName) {{{2
    SetMode(modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.ChangeMode(modeName)
    }

    ; SetModeFunction(func, modeName, winName = "") {{{2
    SetModeFunction(func, modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        modeObj := winObj.modeList[modeName]
        modeObj.modeFunction := func
    }

    ; GetMode(winName) {{{2
    ; 获取指定win中当前的模式
    GetMode(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.modeList[winobj.ExistMode()]
    }

    ; GetInputState {{{2
    ; 0：英文 1：中文
    GetInputState(WinTitle = "A")
    {
        ControlGet, hwnd, HWND, , , %WinTitle%
        if (A_Cursor = "IBeam")
            return 1
        if (WinActive(WinTitle))
        {
            ptrSize := !A_PtrSize ? 4 : A_PtrSize
            VarSetCapacity(stGTI, cbSize := 4 + 4 + (PtrSize * 6) + 16, 0)
            NumPut(cbSize, stGTI, 0, "UInt")   ;   DWORD   cbSize;
            hwnd := DllCall("GetGUIThreadInfo", Uint, 0, Uint, &stGTI)
                             ? NumGet(stGTI, 8 + PtrSize, "UInt") : hwnd
        }
        return DllCall("SendMessage"
            , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, hwnd)
            , UInt, 0x0283  ;Message : WM_IME_CONTROL
            , Int, 0x0005  ;wParam  : IMC_GETOPENSTATUS
            , Int, 0)      ;lParam  : 0
    }

    ; BeforeActionDo(Function, winName = "") {{{2
    BeforeActionDo(Function, winName = "")
    {
        winObj  := this.GetWin(winName)
        winObj.BeforeActionDoFunc := Function
    }

    ; AfterActionDo(Function, winName = "") {{{2
    AfterActionDo(Function, winName = "")
    {
        winObj := this.GetWin(winName)
        winObj.AfterActionDoFunc := Function
    }

    ; SetMaxCount(Int, winName) {{{2
    SetMaxCount(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.MaxCount := int
    }

    ; GetMaxCount(winName) {{{2
    GetMaxCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.MaxCount
    }

    ; SetCount(int, winName) {{{2
    SetCount(int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.Count := int
    }

    ; GetCount(winName) {{{2
    GetCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.Count
    }

    ; SetTimeOut(Int, winName) {{{2
    SetTimeOut(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.TimeOut := int
    }

    ; GetTimeOut(winName) {{{2
    GetTimeOut(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.TimeOut
    }

    ; Map(keyName, Action, winName) {{{2
    ; 例 Map("<C-A>jjj", <a>, "TC")
    ; Map("<nowait>jk", <b>, "TC")
    Map(keyName, Action, winName = "")
    {
        if not this.GetAction(Action)
        {
            if Islabel(action)
                this.SetAction(Action, Action)
            else
            {
                MsgBox % "map " keyname " to "  action  " error"
                this.ErrorCode := "MAP_ACTION_ERROR"
                return
            }
        }

        winObj := This.GetWin(winName)
        modeObj := this.GetMode(winName)
        Class := winObj.class
        filepath := winObj.filepath
        if winName
        {
            if strlen(filepath)
                Hotkey, IfWinActive, ahk_exe %filepath%
            else
                Hotkey, IfWinActive, ahk_class %class%
        }
        else
            Hotkey, IfWinActive
        keyName := RegExReplace(keyName, "i)<nowait>", "", nowait)
        keyName := RegExReplace(keyName, "i)<super>", "", super)
        newkeyName := keyName
        keyIndex := 0
        Loop
        {
            if not strlen(newkeyName)
                break
            else
            {
                saveMoreKey .= thisKey
                modeobj.SetMoreKey(saveMoreKey)
            }

            if RegExMatch(newkeyName, "P)^<.+?>", m)
            {
                thisKey := SubStr(newkeyName, 1, m)
                newkeyName := SubStr(newkeyName, m+1)
            }
            else
            {
                thisKey := SubStr(newkeyName, 1, 1)
                newKeyName := SubStr(newkeyName, 2)
            }

            if RegExMatch(thisKey, "^([A-Z])$", m)
                thisKey := "<S-" m ">"
            SaveKeyName .= thisKey
            key := this.Convert2AHK(thisKey)
            this.Debug.Add("Map: " thiskey " to: " Action)

            if (Action <> "<Default>")
            {
                Hotkey, %Key%, vim_Key, On, UseErrorLevel
            }
            else
            {
                Hotkey, %Key%, Off, UseErrorLevel
            }

            if ErrorLevel
            {
                Msgbox % KeyName "`n" key "`n映射错误"
                this.ErrorCode := "MAP_KEY_ERROR"
                return
            }
            else
            {
                winObj.SuperKeyList[key] := super
                winObj.KeyList[key] := true
                keyIndex++
            }
        }

        modeObj.SetKeyMap(SavekeyName, Action)
        modeObj.SetNoWait(SavekeyName, nowait)
        return false
    }

    ; ExcludeWin(winName = "", Bold = true) {{{2
    ExcludeWin(winName = "", Bold = true)
    {
        this.ExcludeWinList[winName] := Bold
    }

    ; Toggle(winName) {{{2
    Toggle(winName)
    {
        winObj := this.GetWin(winName)
        winObj.Status := !winObj.Status
        this.Control(winObj.Status, winName)
        return winObj.Status
    }

    ; Control(bold, winName) {{{2
    Control(bold, winName = "", all=false)
    {
        winObj := this.GetWin(winName)
        class := winObj.Class
        filepath := winObj.filepath
        if Strlen(filepath)
            Hotkey, IfWinActive, ahk_exe %filepath%
        else if Strlen(class)
            Hotkey, IfWinActive, ahk_class %class%
        else
            Hotkey, IfWinActive

        this.Debug.Add("===== Control End  =====")
        for i , k in winObj.KeyList
        {
            if winObj.SuperKeyList[i] And (not all)
                Continue
            this.Debug.Add("class: " class "`tkey: " i "`tcontrol: " bold)
            if bold
                Hotkey, %i%, vim_Key, On
            else
                Hotkey, %i%, vim_Key, off
            winObj.KeyList[i] := bold
        }
        this.Debug.Add("===== Control Start =====")
    }

    ; Copy(winName1, winName2) {{{2
    ; 复制winName1到winName2, winName2按class/filepath/title定义
    Copy(winName1, winName2, class, filepath = "", title = "")
    {
        this.debug.Add("Copy>> "winName1 "`t"  winName2 "`t" class)
        win1 := This.GetWin(winName1)
        win2 := this.SetWin(winName2, class, filepath, title)
        win2.class := class
        win2.filepath := filepath
        win2.title := title
        win2.KeyList := win1.KeyList
        win2.SuperKeyList := win1.SuperKeyList
        win2.modeList  := win1.modeList
        win2.mode      := win1.mode
        win2.LastKey   := win1.LastKey
        win2.KeyTemp   := win1.KeyTemp
        win2.MaxCount  := win1.MaxCount
        win2.Count     := win1.Count
        win2.TimeOut   := win1.TimeOut
        win2.Info      := win1.Info
        win2.BeforeActionDoFunc := win1.BeforeActionDoFunc
        win2.AfterActionDoFunc  := win1.AfterActionDoFunc
        win2.ShowInfoFunc := win1.ShowInfoFunc
        win2.HideInfoFunc := win1.HideInfoFunc
        this.Control(Bold := true, winName2, all := true)
        return win2
    }

    ; CopyMode(win, mode, to) {{{2
    ; 在当前的Win中复制一个模式
    CopyMode(winName, fromMode, toMode)
    {
        winObj := This.GetWin(winName)
        winObj.mode := modeName
        winObj.KeyTemp := ""
        winObj.Count := 0
        from := winObj.modeList[fromMode]
        from.name  := toMode
        winObj.modeList[toMode] := from
        return from
    }

    ; Delete(winName) {{{2
    Delete(winName = "")
    {
        this.Control(false, winName, all := true)
        this.WinList[winName] := ""
    }

    ; GetMore() {{{2
    GetMore(obj = false)
    {
        rt_obj := []
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        if Strlen(winObj.KeyTemp)
        {
            r := winObj.KeyTemp "`n"
            rt_obj[1] := {"key":winObj.KeyTemp, "Action":modeObj.GetKeyMap(winObj.KeyTemp)}
            m := "i)^" this.ToMatch(winObj.KeyTemp) ".+"
            for i , k in modeObj.keymapList
            {
                if RegExMatch(i, m)
                {
                    r .= i "`t" modeObj.GetKeyMap(i) "`n"
                    rt_obj[rt_obj.MaxIndex()+1] := {"key":i, "Action":modeObj.GetKeyMap(i)}
                }
            }

            if obj
                return rt_obj
            else
                return r
        }
        else
            if winobj.count
                return winobj.count
    }

    ; Clear() {{{2
    Clear(winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.KeyTemp := ""
        winObj.Count := 0
    }

    ; Key() {{{2
    Key()
    {
        ; 获取winName
        winName := this.CheckWin()
        ; 获取当前的热键
        k := this.CheckCapsLock(this.Convert2VIM(A_ThisHotkey))
        ; 如果winName在排除窗口中，直接发送热键
        if this.ExcludeWinList[winName]
        {
            Send, % this.Convert2AHK(k, ToSend := true)
            return
        }
        ; 如果当前热键在当前winName无效，判断全局热键中是否有效？
        winObj := this.GetWin(winName)
        if Not winObj.KeyList[A_thisHotkey]
        {
            winObj := this.GetWin()
            if Not winObj.KeyList[A_thisHotkey]
            {
                ; 无效热键，按普通键输出
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
            else
                winName := ""
        }

        this.LastFoundWin := winName
        ; 执行在判断热键前的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.BeforeActionDoFunc)
        {
            if %f%()
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
        }

        ; 获取当前模式对应的对象
        modeObj := this.GetMode(winName)
        ; 把当前热键添加到热键缓存中, 并设置最后热键为k
        winObj.KeyTemp .= winObj.LastKey := k
        this.Debug.Add(" win: " winname "`tHotkey: " k)

        /*
            if winObj.Count
                this.Debug.Add(" [" winName "`t热键:" winObj.Count winObj.KeyTemp)
            else
                this.Debug.Add(" [" winName "]`t热键:" winObj.KeyTemp)
        */

        ; 热键缓存是否有对应的Action?
        ; 判断是否有更多热键, 如果当前具有<nowait>设置，则无视更多热键
        if modeObj.GetMoreKey(winObj.KeyTemp) And (Not modeObj.GetNoWait(winObj.KeyTemp))
        {
            ; 启用TimeOut
            if strlen(modeObj.GetKeymap(winObj.KeyTemp))
                if tick := winObj.TimeOut
                    Settimer, Vim_TimeOut, %tick%

            winObj.ShowMore()
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                    Send, % this.Convert2AHK(k, ToSend := true)
            }

            return
        }

        ; 如果没有更多，热键缓存是否有对应的Action?
        if strlen(actionName := modeObj.GetKeymap(winObj.KeyTemp))
        {
            actObj := this.GetAction(actionName)
            if (actObj.Type = 0) And RegExMatch(actionName , "^<(\d)>$", m)
            {
                ; 数字则进行累加
                winObj.Count := winObj.Count * 10 + m1
                if winObj.MaxCount And winObj.Count > winObj.MaxCount
                    winObj.Count := winObj.MaxCount

                winObj.KeyTemp := ""
                winObj.ShowMore()
                if IsFunc(f := winObj.AfterActionDoFunc)
                    %f%()
                return
            }
            else
            {
                ; 非数字则直接运行
                ;this.Debug.Add("act: " actionName "`tLK: " winObj.KeyTemp)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                Settimer, Vim_TimeOut, Off
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
        }
        else
        {
            Settimer, Vim_TimeOut, Off
            ; 如果没有，按普通键输出
            if strlen(actionName := modeObj.GetKeymap(winObj.LastKey))
            {
                actObj := this.GetAction(actionName)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
            else
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                winObj.Count := 0
            }
        }

        winObj.KeyTemp := ""
        winObj.HideMore()
        ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.AfterActionDoFunc)
        {
            if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            ; %f%() ;直接运行
        }
        return
    }

    ; IsTimeOut() {{{2
    IsTimeOut()
    {
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        act := this.GetAction(modeObj.GetKeyMap(winObj.KeyTemp))
        if act
        {
            winObj.HideMore()
            __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
            act.Do(winObj.Count)
            winObj.Count := 0
            winObj.KeyTemp := ""
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            }
            Settimer, Vim_TimeOut, Off
        }
    }

    ; Debug(Bold) {{{2
    Debug(Bold, history = false)
    {
        if Bold
        {
            this.Debug := new __vimDebug(history)
            this.Debug.var(this)
        }
        else
        {
            GUI, vimDebug:Destroy
            this.Debug := ""
        }
    }

    ; Convert2VIM(key) {{{2
    ; 将AHK热键名转换为类VIM的热键名
    ; 例 Convert2VIM("f1")
    Convert2VIM(key)
    {
        if RegExMatch(key, "^[A-Z]$")
            return "<S-" this.Upper(key) ">"
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((BS)|(BackSpace))$")
            return "<BS>"
        if RegExMatch(key, "i)^((Esc)|(Escape))$")
            return "<Esc>"
        if RegExMatch(key, "i)^((Ins)|(Insert))$")
            return "<Insert>"
        if RegExMatch(key, "i)^((Del)|(Delete))$")
            return "<Delete>"
        if RegExMatch(key, "i)^PrintScreen$")
            return "<PrtSc>"
        if RegExMatch(key, "i)^shift\s&\s(.*)", m) or RegExMatch(key, "^\+(.*)", m)
            return "<S-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lshift\s&\s(.*)", m) or RegExMatch(key, "^<\+(.*)", m)
            return "<LS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rshift\s&\s(.*)", m) or RegExMatch(key, "^>\+(.*)", m)
            return "<RS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^Ctrl\s&\s(.*)", m) or RegExMatch(key, "^\^(.*)", m)
            return "<C-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lctrl\s&\s(.*)", m) or RegExMatch(key, "^<\^(.*)", m)
            return "<LC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rctrl\s&\s(.*)", m) or RegExMatch(key, "^>\^(.*)", m)
            return "<RC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt\s&\s(.*)", m) or RegExMatch(key, "^\!(.*)", m)
            return "<A-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lalt\s&\s(.*)", m) or RegExMatch(key, "^<\!(.*)", m)
            return "<LA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^ralt\s&\s(.*)", m) or RegExMatch(key, "^>\!(.*)", m)
            return "<RA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lwin\s&\s(.*)", m) or RegExMatch(key, "^#(.*)", m)
            return "<W-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^space\s&\s(.*)", m)
            return "<SP-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt$")
            return "<Alt>"
        if RegExMatch(key, "i)^ctrl$")
            return "<Ctrl>"
        if RegExMatch(key, "i)^shift$")
            return "<Shift>"
        if RegExMatch(key, "i)^lwin$")
            return "<Win>"
        return key
    }

    Upper(k)
    {
        StringUpper, k, k
        return k
    }

    ; Convert2AHK(key, ToSend=false) {{{2
    ; 将类VIM的热键名转换为AHK热键名
    ; 例 Convert2AHK("<F1>")
    Convert2AHK(key, ToSend=false)
    {
        this.CheckCapsLock(key)
        if RegExMatch(key, "^<.*>$")
        {
            key := SubStr(key, 2, strlen(key)-2)
            if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^PrtSc$")
                return ToSend ? "{PrintScreen}" : "PrintScreen"
            if RegExMatch(key, "i)^alt$")
                return ToSend ? "{!}" : "alt"
            if RegExMatch(key, "i)^ctrl$")
                return ToSend ? "{^}" : "ctrl"
            if RegExMatch(key, "i)^shift$")
                return ToSend ? "{+}" : "shift"
            if RegExMatch(key, "i)^win$")
                return ToSend ? "{#}" : "lwin"
            if RegExMatch(key, "<LT>")
                return "<"
            if RegExMatch(key, "<RT>")
                return ">"
            if RegExMatch(key, "i)^S\-(.*)", m)
                return ToSend ? "+" this.CheckToSend(m1) : "+" m1
            if RegExMatch(key, "i)^LS\-(.*)", m)
                return ToSend ? "<+" this.CheckToSend(m1) : "<+" m1
            if RegExMatch(key, "i)^RS-(.*)", m)
                return ToSend ? ">+" this.CheckToSend(m1) : ">+" m1
            if RegExMatch(key, "i)^C\-(.*)", m)
                return ToSend ? "^" this.CheckToSend(m1) : "^" m1
            if RegExMatch(key, "i)^LC\-(.*)", m)
                return ToSend ? "<^" this.CheckToSend(m1) : "<^" m1
            if RegExMatch(key, "i)^RC\-(.*)", m)
                return ToSend ? ">^" this.CheckToSend(m1) : ">^" m1
            if RegExMatch(key, "i)^A\-(.*)", m)
                return ToSend ? "!" this.CheckToSend(m1) : "!" m1
            if RegExMatch(key, "i)^LA\-(.*)", m)
                return ToSend ? "<!" this.CheckToSend(m1) : "<!" m1
            if RegExMatch(key, "i)^RA\-(.*)", m)
                return ToSend ? ">!" this.CheckToSend(m1) : ">!" m1
            if RegExMatch(key, "i)^w\-(.*)", m)
                return ToSend ? "#" this.CheckToSend(m1) : "#" m1
            if RegExMatch(key, "i)^SP\-(.*)", m)
                return ToSend ? "{space}" this.CheckToSend(m1) : "space & " m1
        }
        else
            return key
    }

    CheckToSend(key)
    {
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "{" key "}"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
            return "{" key "}"
        if RegExMatch(key, "i)^PrtSc$")
            return "{PrintScreen}"
        if RegExMatch(key, "i)^alt$")
            return "{!}"
        if RegExMatch(key, "i)^ctrl$")
            return "{^}"
        if RegExMatch(key, "i)^shift$")
            return "{+}"
        if RegExMatch(key, "i)^win$")
            return "{#}"
        if RegExMatch(key, "<LT>")
            return "<"
        if RegExMatch(key, "<RT>")
            return ">"
        return Key
    }

    ; CheckCapsLock(key) {{{2
    ; 检测CapsLock是否按下，返回对应的值
    ; key 的值为类VIM键，如 CheckCapsLock("<S-A>")
    CheckCapsLock(key)
    {
        if GetKeyState("CapsLock", "T")
        {
            if RegExMatch(key, "^[a-z]$")
                return "<S-" key ">"
            if RegExMatch(key, "i)^<S\-([a-zA-Z])>", m)
            {
                StringLower, key, m1
                return key
            }
        }
        return key
    }

    ToMatch(v)
    {
        v := RegExReplace(v , "\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\", "\$0")
        return RegExReplace(v , "\s", "\s")
    }
}

; Class __win {{{1
Class __win
{
    __new(class = "", filepath = "", title = "")
    {
        this.class     := class
        this.filepath  := filepath
        this.title     := title
        this.KeyList   := []
        this.SuperKeyList   := []
        this.modeList  := []
        this.Status    := true
        this.mode      := ""
        this.LastKey   := ""
        this.KeyTemp   := ""
        this.MaxCount  := 99
        this.Count     := 0
        this.TimeOut   := 0
        this.Info := default_enable_show_info
        this.BeforeActionDoFunc := ""
        this.AfterActionDoFunc   := ""
        this.ShowInfoFunc := "ShowInfo"
        this.HideInfoFunc := "HideInfo"
    }

    ; ChangeMode(modeName) {{{2
    ; 检查模式是否存在，如存在则返回模式对象，如果不存在则新建并返回模式对象
    ChangeMode(modeName)
    {
        this.mode := modeName
        this.KeyTemp := ""
        this.Count := 0
        if not this.modeList[modeName]
            this.modeList[modeName] := new __Mode(modeName)

        modeObj := this.modeList[modeName]
        if IsFunc(func := modeObj.modeFunction)
            %func%()
        return modeObj
    }

    ; ExistMode() {{{2
    ; 获取当前模式名
    ExistMode()
    {
        return this.mode
    }

    ; SetInfo() {{{2
    SetInfo(bold)
    {
        this.info := bold
    }

    ; SetShowInfo() {{{2
    SetShowInfo(func)
    {
        this.ShowInfoFunc := func
    }

    ; SetHideInfo() {{{2
    SetHideInfo(func)
    {
        this.HideInfoFunc := func
    }

    ; ShowMore() {{{2
    ShowMore()
    {
        if IsFunc(f := this.ShowInfoFunc) And this.Info
            %f%()
    }

    ; HideMore() {{{2
    HideMore()
    {
        if IsFunc(f:=this.HideInfoFunc) And this.Info
            %f%()
    }
}

; Class __Mode {{{1
Class __Mode
{
    __new(modeName)
    {
        this.name  := modeName
        this.keymapList := []
        this.keymoreList := []
        this.nowaitList := []
        this.modeFunction := ""
    }

    ; SetKeyMap(key, action) {{{2
    SetKeyMap(key, action)
    {
        this.keymapList[key] := action
    }

    ; GetKeyMap(key) {{{2
    GetKeyMap(key)
    {
        return this.keymapList[key]
    }

    ; DelKeyMap(key) {{{2
    DelKeyMap(key)
    {
        this.keymapList[key] := ""
    }

    ; SetNoWait(key, bold) {{{2
    ; 无视TimeOut执行热键
    SetNoWait(key, bold)
    {
        this.nowaitList[key] := bold
    }

    ; GetNoWait(key) {{{2
    GetNoWait(key)
    {
        return this.nowaitList[key]
    }

    ; SetMoreKey(key) {{{2
    SetMoreKey(key)
    {
        this.keymoreList[key] := true
    }

    ; GetMoreKey(key) {{{2
    GetMoreKey(key)
    {
        return this.keymoreList[key]
    }
}

; Class __Action {{{1
Class __Action
{
    ; Action 有几种类型
    ; 0 代表执行Action对应的Label (默认)
    ; 1 代表执行Function的值对应的函数
    ; 2 代表运行CmdLine对应的值
    ; 3 代表发送HotString对应的文本

    __new(Name, Comment)
    {
        this.Name := Name
        this.Comment := Comment
        this.MaxTimes := 0
        this.Type := 0
        this.Function := ""
        this.CmdLine := ""
        this.HotString := ""
    }

    ; SetFunction(Function) {{{2
    ; 设置Action执行的函数名
    SetFunction(Function)
    {
        this.Function := Function
        this.Type := 1
    }

    ; SetCmdLine(CmdLine) {{{2
    ; 设置Action运行的字符串
    SetCmdLine(CmdLine)
    {
        this.CmdLine := CmdLine
        this.Type := 2
    }

    ; SetHotString(HotString) {{{2
    ; 设置Action发送的文本
    SetHotString(HotString)
    {
        this.HotString := HotString
        this.Type := 3
    }

    ; SetMaxTimes(Times) {{{2
    ; 设置最大运行次数
    SetMaxTimes(Times)
    {
        this.MaxTimes := Times
    }

    ; Do(Times=1) {{{2
    ; 执行Action
    Do(Times=0)
    {
        Times := !Times ? 1 : Times
        if this.MaxTimes And (Times > this.MaxTimes)
            Times := this.MaxTimes
        Loop, %Times%
        {
            if this.Type = 0
            {
                if IsLabel(label := this.Name)
                    GoSub, %label%
            }
            else if this.Type = 1
            {
                if IsFunc(f := this.Function)
                    %f%()
            }
            else if this.Type = 2
            {
                c := this.CmdLine
                Run, %cmd%
            }
            else if This.Type = 3
            {
                t := this.HotString
                Send, %t%
            }
        }
    }
}

; Class __Plugin {{{1
Class __Plugin
{
    __new(PluginName)
    {
        this.PluginName := PluginName
        this.Author := ""
        this.Ver := ""
        this.Comment := ""
    }

    ; CheckSub() {{{2
    CheckSub()
    {
        if IsLabel(p := this.PluginName)
        {
            GoSub, %p%
            this.Error := false
        }
        else
            this.Error := true
    }
}

; Class __vimDebug {{{1
Class __vimDebug
{
    __new(key)
    {
        this.mode := key
        if key
        {
            GUI, vimDebug:Destroy
            GUI, vimDebug:+hwnd_vimdebug -Caption +ToolWindow +Border
            GUI, vimDebug:color, 454545, 454545
            GUI, vimDebug:font, s16 cFFFFFF
            GUI, vimDebug:Add, Edit, x-2 y-2 w400 h60 readonly
            GUI, vimDebug:Show, w378 h56 y600
            WinSet, AlwaysOnTop, On, ahk_id %_vimdebug%
        }
        else
        {
            GUI, vimDebug:font, s12
            GUI, vimDebug:Destroy
            GUI, vimDebug:Add, Edit, x10 y10 w400 h300 readonly
            GUI, vimDebug:Add, Edit, x10 y320 w400 h26 readonly
            GUI, vimDebug:Show, w420 h356
        }
    }

    var(obj)
    {
        this.vim := obj
    }

    Set(v)
    {
        winName := this.vim.CheckWin()
        winObj := this.vim.GetWin(winName)
        if winObj.Count
            k := " 热键缓存:" winObj.Count winObj.KeyTemp
        else
             k := " 热键缓存:" winObj.KeyTemp
        GUI, vimDebug:Default
        GUIControl, , Edit1, %v%
        GUIControl, , Edit2, %k%
    }

    Get()
    {
        GUI, vimDebug:Default
        GUIControlGet, v, , Edit1
        return v
    }

    ; Add(v) {{{2
    Add(v)
    {
        b := this.Get()
        if this.mode
            this.Set(b)
        else
            this.Set(v "`n" b)
    }

    ; Clear() {{{2
    Clear()
    {
        this.Set("")
    }
}

; 初始化class_Vim

vim_Init:
    #UseHook
    SetKeyDelay, -1
return

; 用于热键映射
vim_Key:
    vim.Key()
return

; 用于热键超时
vim_TimeOut:
    vim.IsTimeOut()
return

; 用于Count计数
Internal:
    __v.SetPlugin("Internal", "Array", "0.1", "内置插件")
    __v.SetAction("<1>", "数字 1")
    __v.SetAction("<2>", "数字 2")
    __v.SetAction("<3>", "数字 3")
    __v.SetAction("<4>", "数字 4")
    __v.SetAction("<5>", "数字 5")
    __v.SetAction("<6>", "数字 6")
    __v.SetAction("<7>", "数字 7")
    __v.SetAction("<8>", "数字 8")
    __v.SetAction("<9>", "数字 9")
    __v.SetAction("<0>", "数字 0")
    __v.SetAction("<>", "空操作")
    __v.SetAction("<Pass>", "空操作")
    __v.SetAction("<Default>", "恢复默认")
    __v := ""
return

<1>:
<2>:
<3>:
<4>:
<5>:
<6>:
<7>:
<8>:
<9>:
<0>:
<>:
<Pass>:
<Default>:
return

Class_vim()
{
    global __v
    GoSub, Vim_Init
    __v := v := new __vim
    __v.LoadPlugin("Internal")
    return v
}

GetLastAction()
{
    global __vimLastAction
    return __vimLastAction
}

ShowInfo()
{
    Global vim
    obj := vim.GetMore(true)
    winObj := vim.GetWin(vim.LastFoundWin)
    if winObj.Count
        np .= winObj.Count
    Loop, % obj.MaxIndex()
    {
        act := vim.GetAction(obj[A_Index]["Action"])

        ; Type = 1 : Function
        if (act.Type = 1)
        {
            ActionDescList := act.Comment
            Key := obj[A_Index]["key"]
            np .= Key "`t" %ActionDescList%[Key] "`n"
        }
        else
        {
            np .= obj[A_Index]["key"] "`t" act.Comment "`n"
        }

        if (A_Index = 1)
            np .= "=====================`n"
    }
    MouseGetPos, posx, posy, A
    posx += 40
    posy += 40
    Tooltip, %np%, %posx%, %posy%
}

HideInfo()
{
    ; 当屏幕有非快捷键补全帮助信息时，不清理
    Global showToolTipStatus
    if (!showToolTipStatus)
    {
        Tooltip
    }
}

; 定义数据结构
; Class __vim {{{1
Class __vim
{
    __new()
    {
        this.PluginList := []
        this.WinList    := []
        this.WinInfo    := []
        this.ActionList := []
        this.ActionFromPlugin := []
        this.ExcludeWinList := []
        this.winGlobal  := new __win
        this.ErrorCode  := 0
        tihs.ActionFromPluginName := ""
        this.LastFoundWin := ""
    }

    ; LoadPlugin(PluginName) {{{2
    ; 用于注册插件
    LoadPlugin(PluginName)
    {
        if this.PluginList[PluginName]
            return this.PluginList[PluginName]
        p := new __Plugin(PluginName)
        this.PluginList[PluginName] := p
        back := this.ActionFromPluginName
        this.ActionFromPluginName := PluginName
        p.CheckSub()
        if p.Error
        {
            MsgBox load plugin "%PluginName%" error
            this.ActionFromPluginName := back
        }
    }

    ; SetPlugin(PluginName, Author = "", Ver = "", Comment = "") {{{2
    ; 设置Plugin信息
    SetPlugin(PluginName, Author = "", Ver = "", Comment = "")
    {
        p := this.PluginList[PluginName]
        p.Author := Author
        p.Ver := Ver
        p.Comment := Comment
    }

    ; GetPlugin(PluginName) {{{2
    ; 获取Plugin信息
    GetPlugin(PluginName)
    {
        return this.PluginList[PluginName]
    }

    ; Comment(Action, Desc, Complex = 1) {{{2
    ; 兼容老版本的vimcore.ahk
    Comment(Action, Desc = "", Complex = 1)
    {
        act := this.SetAction(Action, Desc)
        if not complex ; 不允许多次运行
            act.SetMaxTimes(1)
        return act
    }

    ; SetAction(Name, Comment) {{{2
    ; 用于为Action(动作)进行注释
    SetAction(Name, Comment = "")
    {
        if this.ActionList[Name]
            ra := This.ActionList[Name]
        else
            ra := This.ActionList[Name] := new __Action(Name, Comment)
        This.ActionFromPlugin[Name] := this.ActionFromPluginName
        return ra
    }

    ; GetAction(Name) {{{2
    ; 获取Action的信息
    GetAction(Name)
    {
        return this.ActionList[Name]
    }

    ; SetWin(winName, class, filepath, title) {{{2
    ; 添加win成员
    SetWin(winName, class, filepath = "", title = "")
    {
        if this.WinList[winName]
            rw := this.WinList[winName]
        else
            rw := this.WinList[winName] := new __win(class, filepath, title)
        this.WinInfo["class`t"class]       := winName
        this.WinInfo["filepath`t"filepath] := winName
        this.WinInfo["title`t"title]       := winName
        return rw
    }

    ; GetWin(winName) {{{2
    GetWin(winName = "")
    {
        if strlen(winName)
            return this.WinList[winName]
        else
            return this.winGlobal
    }

    ; CheckWin() {{{2
    CheckWin()
    {
        /*
        WinGetTitle, t, A
        if Strlen(winName := this.WinInfo["title`t"t])
            return winName
        */

        WinGet, f, ProcessName, A
        if Strlen(winName := this.WinInfo["filepath`t"f])
            return winName
        WinGetClass, c, A
        if Strlen(winName := this.WinInfo["class`t"c])
            return winName
    }

    ; mode(mode, win = "") {{{2
    ; 兼容老版本的vimcore.ahk
    mode(mode, win = "")
    {
        if not IsObject(this.GetWin(win))
            this.SetWin(win, win)
        return this.SetMode(mode, win)
    }

    ; SetMode(modeName, winName) {{{2
    SetMode(modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.ChangeMode(modeName)
    }

    ; SetModeFunction(func, modeName, winName = "") {{{2
    SetModeFunction(func, modeName, winName = "")
    {
        winObj := This.GetWin(winName)
        modeObj := winObj.modeList[modeName]
        modeObj.modeFunction := func
    }

    ; GetMode(winName) {{{2
    ; 获取指定win中当前的模式
    GetMode(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.modeList[winobj.ExistMode()]
    }

    ; GetInputState {{{2
    ; 0：英文 1：中文
    GetInputState(WinTitle = "A")
    {
        ControlGet, hwnd, HWND, , , %WinTitle%
        if (A_Cursor = "IBeam")
            return 1
        if (WinActive(WinTitle))
        {
            ptrSize := !A_PtrSize ? 4 : A_PtrSize
            VarSetCapacity(stGTI, cbSize := 4 + 4 + (PtrSize * 6) + 16, 0)
            NumPut(cbSize, stGTI, 0, "UInt")   ;   DWORD   cbSize;
            hwnd := DllCall("GetGUIThreadInfo", Uint, 0, Uint, &stGTI)
                             ? NumGet(stGTI, 8 + PtrSize, "UInt") : hwnd
        }
        return DllCall("SendMessage"
            , UInt, DllCall("imm32\ImmGetDefaultIMEWnd", Uint, hwnd)
            , UInt, 0x0283  ;Message : WM_IME_CONTROL
            , Int, 0x0005  ;wParam  : IMC_GETOPENSTATUS
            , Int, 0)      ;lParam  : 0
    }

    ; BeforeActionDo(Function, winName = "") {{{2
    BeforeActionDo(Function, winName = "")
    {
        winObj  := this.GetWin(winName)
        winObj.BeforeActionDoFunc := Function
    }

    ; AfterActionDo(Function, winName = "") {{{2
    AfterActionDo(Function, winName = "")
    {
        winObj := this.GetWin(winName)
        winObj.AfterActionDoFunc := Function
    }

    ; SetMaxCount(Int, winName) {{{2
    SetMaxCount(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.MaxCount := int
    }

    ; GetMaxCount(winName) {{{2
    GetMaxCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.MaxCount
    }

    ; SetCount(int, winName) {{{2
    SetCount(int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.Count := int
    }

    ; GetCount(winName) {{{2
    GetCount(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.Count
    }

    ; SetTimeOut(Int, winName) {{{2
    SetTimeOut(Int, winName = "")
    {
        winObj := This.GetWin(winName)
        winObj.TimeOut := int
    }

    ; GetTimeOut(winName) {{{2
    GetTimeOut(winName = "")
    {
        winObj := This.GetWin(winName)
        return winObj.TimeOut
    }

    ; Map(keyName, Action, winName) {{{2
    ; 例 Map("<C-A>jjj", <a>, "TC")
    ; Map("<nowait>jk", <b>, "TC")
    Map(keyName, Action, winName = "")
    {
        if not this.GetAction(Action)
        {
            if Islabel(action)
                this.SetAction(Action, Action)
            else
            {
                MsgBox % "map " keyname " to "  action  " error"
                this.ErrorCode := "MAP_ACTION_ERROR"
                return
            }
        }

        winObj := This.GetWin(winName)
        modeObj := this.GetMode(winName)
        Class := winObj.class
        filepath := winObj.filepath
        if winName
        {
            if strlen(filepath)
                Hotkey, IfWinActive, ahk_exe %filepath%
            else
                Hotkey, IfWinActive, ahk_class %class%
        }
        else
            Hotkey, IfWinActive
        keyName := RegExReplace(keyName, "i)<nowait>", "", nowait)
        keyName := RegExReplace(keyName, "i)<super>", "", super)
        newkeyName := keyName
        index := 0
        Loop
        {
            if not strlen(newkeyName)
                break
            else
            {
                saveMoreKey .= thisKey
                modeobj.SetMoreKey(saveMoreKey)
            }

            if RegExMatch(newkeyName, "P)^<.+?>", m)
            {
                thisKey := SubStr(newkeyName, 1, m)
                newkeyName := SubStr(newkeyName, m+1)
            }
            else
            {
                thisKey := SubStr(newkeyName, 1, 1)
                newKeyName := SubStr(newkeyName, 2)
            }

            if RegExMatch(thisKey, "^([A-Z])$", m)
                thisKey := "<S-" m ">"
            SaveKeyName .= thisKey
            key := this.Convert2AHK(thisKey)
            this.Debug.Add("Map: " thiskey " to: " Action)

            if (Action <> "<Default>")
            {
                Hotkey, %Key%, vim_Key, On, UseErrorLevel
            }
            else
            {
                Hotkey, %Key%, Off, UseErrorLevel
            }

            if ErrorLevel
            {
                Msgbox % KeyName "`n" key "`n映射错误"
                this.ErrorCode := "MAP_KEY_ERROR"
                return
            }
            else
            {
                winObj.SuperKeyList[key] := super
                winObj.KeyList[key] := true
                Index++
            }
        }

        modeObj.SetKeyMap(SavekeyName, Action)
        modeObj.SetNoWait(SavekeyName, nowait)
        return false
    }

    ; ExcludeWin(winName = "", Bold = true) {{{2
    ExcludeWin(winName = "", Bold = true)
    {
        this.ExcludeWinList[winName] := Bold
    }

    ; Toggle(winName) {{{2
    Toggle(winName)
    {
        winObj := this.GetWin(winName)
        winObj.Status := !winObj.Status
        this.Control(winObj.Status, winName)
        return winObj.Status
    }

    ; Control(bold, winName) {{{2
    Control(bold, winName = "", all=false)
    {
        winObj := this.GetWin(winName)
        class := winObj.Class
        filepath := winObj.filepath
        if Strlen(filepath)
            Hotkey, IfWinActive, ahk_exe %filepath%
        else if Strlen(class)
            Hotkey, IfWinActive, ahk_class %class%
        else
            Hotkey, IfWinActive

        this.Debug.Add("===== Control End  =====")
        for i , k in winObj.KeyList
        {
            if winObj.SuperKeyList[i] And (not all)
                Continue
            this.Debug.Add("class: " class "`tkey: " i "`tcontrol: " bold)
            if bold
                Hotkey, %i%, vim_Key, On
            else
                Hotkey, %i%, vim_Key, off
            winObj.KeyList[i] := bold
        }
        this.Debug.Add("===== Control Start =====")
    }

    ; Copy(winName1, winName2) {{{2
    ; 复制winName1到winName2, winName2按class/filepath/title定义
    Copy(winName1, winName2, class, filepath = "", title = "")
    {
        this.debug.Add("Copy>> "winName1 "`t"  winName2 "`t" class)
        w1 := This.GetWin(winName1)
        w2 := this.SetWin(winName2, class, filepath, title)
        w2.class := class
        w2.filepath := filepath
        w2.title := title
        w2.KeyList := w1.KeyList
        w2.SuperKeyList := w1.SuperKeyList
        w2.modeList  := w1.modeList
        w2.mode      := w1.mode
        w2.LastKey   := w1.LastKey
        w2.KeyTemp   := w1.KeyTemp
        w2.MaxCount  := w1.MaxCount
        w2.Count     := w1.Count
        w2.TimeOut   := w1.TimeOut
        w2.Info      := w1.Info
        w2.BeforeActionDoFunc := w1.BeforeActionDoFunc
        w2.AfterActionDoFunc  := w1.AfterActionDoFunc
        w2.ShowInfoFunc := w1.ShowInfoFunc
        w2.HideInfoFunc := w1.HideInfoFunc
        this.Control(Bold := true, winName2, all := true)
        return w2
    }

    ; CopyMode(win, mode, to) {{{2
    ; 在当前的Win中复制一个模式
    CopyMode(winName, fromMode, toMode)
    {
        winObj := This.GetWin(winName)
        winObj.mode := modeName
        winObj.KeyTemp := ""
        winObj.Count := 0
        from := winObj.modeList[fromMode]
        from.name  := toMode
        winObj.modeList[toMode] := from
        return from
    }

    ; Delete(winName) {{{2
    Delete(winName = "")
    {
        this.Control(false, winName, all := true)
        this.WinList[winName] := ""
    }

    ; GetMore() {{{2
    GetMore(obj = false)
    {
        rt_obj := []
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        if Strlen(winObj.KeyTemp)
        {
            r := winObj.KeyTemp "`n"
            rt_obj[1] := {"key":winObj.KeyTemp, "Action":modeObj.GetKeyMap(winObj.KeyTemp)}
            m := "i)^" this.ToMatch(winObj.KeyTemp) ".+"
            for i , k in modeObj.keymapList
            {
                if RegExMatch(i, m)
                {
                    r .= i "`t" modeObj.GetKeyMap(i) "`n"
                    rt_obj[rt_obj.MaxIndex()+1] := {"key":i, "Action":modeObj.GetKeyMap(i)}
                }
            }

            if obj
                return rt_obj
            else
                return r
        }
        else
            if winobj.count
                return winobj.count
    }

    ; Clear() {{{2
    Clear(winName = "") {
        winObj := This.GetWin(winName)
        winObj.KeyTemp := ""
        winObj.Count := 0
    }

    ; Key() {{{2
    Key()
    {
        Global __vimLastAction
        ; 获取winName
        winName := this.CheckWin()
        ; 获取当前的热键
        k := this.CheckCapsLock(this.Convert2VIM(A_ThisHotkey))
        ; 如果winName在排除窗口中，直接发送热键
        if this.ExcludeWinList[winName]
        {
            Send, % this.Convert2AHK(k, ToSend := true)
            return
        }
        ; 如果当前热键在当前winName无效，判断全局热键中是否有效？
        winObj := this.GetWin(winName)
        if Not winObj.KeyList[A_thisHotkey]
        {
            winObj := this.GetWin()
            if Not winObj.KeyList[A_thisHotkey]
            {
                ; 无效热键，按普通键输出
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
            else
                winName := ""
        }

        this.LastFoundWin := winName
        ; 执行在判断热键前的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.BeforeActionDoFunc)
        {
            if %f%()
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                return
            }
        }

        ; 获取当前模式对应的对象
        modeObj := this.GetMode(winName)
        ; 把当前热键添加到热键缓存中, 并设置最后热键为k
        winObj.KeyTemp .= winObj.LastKey := k
        this.Debug.Add(" win: " winname "`tHotkey: " k)

        /*
            if winObj.Count
                this.Debug.Add(" [" winName "`t热键:" winObj.Count winObj.KeyTemp)
            else
                this.Debug.Add(" [" winName "]`t热键:" winObj.KeyTemp)
        */

        ; 热键缓存是否有对应的Action?
        ; 判断是否有更多热键, 如果当前具有<nowait>设置，则无视更多热键
        if modeObj.GetMoreKey(winObj.KeyTemp) And (Not modeObj.GetNoWait(winObj.KeyTemp))
        {
            ; 启用TimeOut
            if strlen(modeObj.GetKeymap(winObj.KeyTemp))
                if tick := winObj.TimeOut
                    Settimer, Vim_TimeOut, %tick%

            winObj.ShowMore()
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                    Send, % this.Convert2AHK(k, ToSend := true)
            }

            return
        }

        ; 如果没有更多，热键缓存是否有对应的Action?
        if strlen(actionName := modeObj.GetKeymap(winObj.KeyTemp))
        {
            actObj := this.GetAction(actionName)
            if (actObj.Type = 0) And RegExMatch(actionName , "^<(\d)>$", m)
            {
                ; 数字则进行累加
                winObj.Count := winObj.Count * 10 + m1
                if winObj.MaxCount And winObj.Count > winObj.MaxCount
                    winObj.Count := winObj.MaxCount

                winObj.KeyTemp := ""
                winObj.ShowMore()
                if IsFunc(f := winObj.AfterActionDoFunc)
                    %f%()
                return
            }
            else
            {
                ; 非数字则直接运行
                ;this.Debug.Add("act: " actionName "`tLK: " winObj.KeyTemp)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                Settimer, Vim_TimeOut, Off
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
        }
        else
        {
            Settimer, Vim_TimeOut, Off
            ; 如果没有，按普通键输出
            if strlen(actionName := modeObj.GetKeymap(winObj.LastKey))
            {
                actObj := this.GetAction(actionName)
                __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
                actObj.Do(winObj.Count)
                winObj.Count := 0
            }
            else
            {
                Send, % this.Convert2AHK(k, ToSend := true)
                winObj.Count := 0
            }
        }

        winObj.KeyTemp := ""
        winObj.HideMore()
        ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
        if IsFunc(f := winObj.AfterActionDoFunc)
        {
            if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            ; %f%() ;直接运行
        }
        return
    }

    ; IsTimeOut() {{{2
    IsTimeOut()
    {
        winObj  := this.GetWin(this.LastFoundWin)
        modeObj := this.GetMode(this.LastFoundWin)
        act := this.GetAction(modeObj.GetKeyMap(winObj.KeyTemp))
        if act
        {
            winObj.HideMore()
            __vimLastAction := {"LastKey":k, "winName":winName, "ActionName":ActionName, "KeyTemp":winObj.KeyTemp, "Count":winObj.Count}
            act.Do(winObj.Count)
            winObj.Count := 0
            winObj.KeyTemp := ""
            ; 执行在判断热键后的函数, 如果函数返回true，按普通键输出
            if IsFunc(f := winObj.AfterActionDoFunc)
            {
                if %f%()
                Send, % this.Convert2AHK(k, ToSend := true)
            }
            Settimer, Vim_TimeOut, Off
        }
    }

    ; Debug(Bold) {{{2
    Debug(Bold, history = false)
    {
        if Bold
        {
            this.Debug := new __vimDebug(history)
            this.Debug.var(this)
        }
        else
        {
            GUI, vimDebug:Destroy
            this.Debug := ""
        }
    }

    ; Convert2VIM(key) {{{2
    ; 将AHK热键名转换为类VIM的热键名
    ; 例 Convert2VIM("f1")
    Convert2VIM(key)
    {
        if RegExMatch(key, "^[A-Z]$")
            return "<S-" this.Upper(key) ">"
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn))$")
            return "<" key ">"
        if RegExMatch(key, "i)^((BS)|(BackSpace))$")
            return "<BS>"
        if RegExMatch(key, "i)^((Esc)|(Escape))$")
            return "<Esc>"
        if RegExMatch(key, "i)^((Ins)|(Insert))$")
            return "<Insert>"
        if RegExMatch(key, "i)^((Del)|(Delete))$")
            return "<Delete>"
        if RegExMatch(key, "i)^PrintScreen$")
            return "<PrtSc>"
        if RegExMatch(key, "i)^shift\s&\s(.*)", m) or RegExMatch(key, "^\+(.*)", m)
            return "<S-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lshift\s&\s(.*)", m) or RegExMatch(key, "^<\+(.*)", m)
            return "<LS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rshift\s&\s(.*)", m) or RegExMatch(key, "^>\+(.*)", m)
            return "<RS-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^Ctrl\s&\s(.*)", m) or RegExMatch(key, "^\^(.*)", m)
            return "<C-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lctrl\s&\s(.*)", m) or RegExMatch(key, "^<\^(.*)", m)
            return "<LC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^rctrl\s&\s(.*)", m) or RegExMatch(key, "^>\^(.*)", m)
            return "<RC-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt\s&\s(.*)", m) or RegExMatch(key, "^\!(.*)", m)
            return "<A-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lalt\s&\s(.*)", m) or RegExMatch(key, "^<\!(.*)", m)
            return "<LA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^ralt\s&\s(.*)", m) or RegExMatch(key, "^>\!(.*)", m)
            return "<RA-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^lwin\s&\s(.*)", m) or RegExMatch(key, "^#(.*)", m)
            return "<W-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^space\s&\s(.*)", m)
            return "<SP-" this.Upper(m1) ">"
        if RegExMatch(key, "i)^alt$")
            return "<Alt>"
        if RegExMatch(key, "i)^ctrl$")
            return "<Ctrl>"
        if RegExMatch(key, "i)^shift$")
            return "<Shift>"
        if RegExMatch(key, "i)^lwin$")
            return "<Win>"
        return key
    }

    Upper(k)
    {
        StringUpper, k, k
        return k
    }

    ; Convert2AHK(key, ToSend=false) {{{2
    ; 将类VIM的热键名转换为AHK热键名
    ; 例 Convert2AHK("<F1>")
    Convert2AHK(key, ToSend=false)
    {
        this.CheckCapsLock(key)
        if RegExMatch(key, "^<.*>$")
        {
            key := SubStr(key, 2, strlen(key)-2)
            if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
                return ToSend ? "{" key "}" : key
            if RegExMatch(key, "i)^PrtSc$")
                return ToSend ? "{PrintScreen}" : "PrintScreen"
            if RegExMatch(key, "i)^alt$")
                return ToSend ? "{!}" : "alt"
            if RegExMatch(key, "i)^ctrl$")
                return ToSend ? "{^}" : "ctrl"
            if RegExMatch(key, "i)^shift$")
                return ToSend ? "{+}" : "shift"
            if RegExMatch(key, "i)^win$")
                return ToSend ? "{#}" : "lwin"
            if RegExMatch(key, "<LT>")
                return "<"
            if RegExMatch(key, "<RT>")
                return ">"
            if RegExMatch(key, "i)^S\-(.*)", m)
                return ToSend ? "+" this.CheckToSend(m1) : "+" m1
            if RegExMatch(key, "i)^LS\-(.*)", m)
                return ToSend ? "<+" this.CheckToSend(m1) : "<+" m1
            if RegExMatch(key, "i)^RS-(.*)", m)
                return ToSend ? ">+" this.CheckToSend(m1) : ">+" m1
            if RegExMatch(key, "i)^C\-(.*)", m)
                return ToSend ? "^" this.CheckToSend(m1) : "^" m1
            if RegExMatch(key, "i)^LC\-(.*)", m)
                return ToSend ? "<^" this.CheckToSend(m1) : "<^" m1
            if RegExMatch(key, "i)^RC\-(.*)", m)
                return ToSend ? ">^" this.CheckToSend(m1) : ">^" m1
            if RegExMatch(key, "i)^A\-(.*)", m)
                return ToSend ? "!" this.CheckToSend(m1) : "!" m1
            if RegExMatch(key, "i)^LA\-(.*)", m)
                return ToSend ? "<!" this.CheckToSend(m1) : "<!" m1
            if RegExMatch(key, "i)^RA\-(.*)", m)
                return ToSend ? ">!" this.CheckToSend(m1) : ">!" m1
            if RegExMatch(key, "i)^w\-(.*)", m)
                return ToSend ? "#" this.CheckToSend(m1) : "#" m1
            if RegExMatch(key, "i)^SP\-(.*)", m)
                return ToSend ? "{space}" this.CheckToSend(m1) : "space & " m1
        }
        else
            return key
    }

    CheckToSend(key)
    {
        if RegExMatch(key, "i)^((F1)|(F2)|(F3)|(F4)|(F5)|(F6)|(F7)|(F8)|(F9)|(F10)|(F11)|(F12))$")
            return "{" key "}"
        if RegExMatch(key, "i)^((AppsKey)|(Tab)|(Enter)|(Space)|(Home)|(End)|(CapsLock)|(ScroollLock)|(Up)|(Down)|(Left)|(Right)|(PgUp)|(PgDn)|(BS)|(ESC)|(Insert)|(Delete))$")
            return "{" key "}"
        if RegExMatch(key, "i)^PrtSc$")
            return "{PrintScreen}"
        if RegExMatch(key, "i)^alt$")
            return "{!}"
        if RegExMatch(key, "i)^ctrl$")
            return "{^}"
        if RegExMatch(key, "i)^shift$")
            return "{+}"
        if RegExMatch(key, "i)^win$")
            return "{#}"
        if RegExMatch(key, "<LT>")
            return "<"
        if RegExMatch(key, "<RT>")
            return ">"
        return Key
    }

    ; CheckCapsLock(key) {{{2
    ; 检测CapsLock是否按下，返回对应的值
    ; key 的值为类VIM键，如 CheckCapsLock("<S-A>")
    CheckCapsLock(key)
    {
        if GetKeyState("CapsLock", "T")
        {
            if RegExMatch(key, "^[a-z]$")
                return "<S-" key ">"
            if RegExMatch(key, "i)^<S\-([a-zA-Z])>", m)
            {
                StringLower, key, m1
                return key
            }
        }
        return key
    }

    ToMatch(v)
    {
        v := RegExReplace(v , "\+|\?|\.|\*|\{|\}|\(|\)|\||\^|\$|\[|\]|\\", "\$0")
        return RegExReplace(v , "\s", "\s")
    }
}

; Class __win {{{1
Class __win
{
    __new(class = "", filepath = "", title = "")
    {
        this.class     := class
        this.filepath  := filepath
        this.title     := title
        this.KeyList   := []
        this.SuperKeyList   := []
        this.modeList  := []
        this.Status    := true
        this.mode      := ""
        this.LastKey   := ""
        this.KeyTemp   := ""
        this.MaxCount  := 99
        this.Count     := 0
        this.TimeOut   := 0
        this.Info := default_enable_show_info
        this.BeforeActionDoFunc := ""
        this.AfterActionDoFunc   := ""
        this.ShowInfoFunc := "ShowInfo"
        this.HideInfoFunc := "HideInfo"
    }

    ; ChangeMode(modeName) {{{2
    ; 检查模式是否存在，如存在则返回模式对象，如果不存在则新建并返回模式对象
    ChangeMode(modeName)
    {
        this.mode := modeName
        this.KeyTemp := ""
        this.Count := 0
        if not this.modeList[modeName]
            this.modeList[modeName] := new __Mode(modeName)

        modeObj := this.modeList[modeName]
        if IsFunc(func := modeObj.modeFunction)
            %func%()
        return modeObj
    }

    ; ExistMode() {{{2
    ; 获取当前模式名
    ExistMode()
    {
        return this.mode
    }

    ; SetInfo() {{{2
    SetInfo(bold)
    {
        this.info := bold
    }

    ; SetShowInfo() {{{2
    SetShowInfo(func)
    {
        this.ShowInfoFunc := func
    }

    ; SetHideInfo() {{{2
    SetHideInfo(func)
    {
        this.HideInfoFunc := func
    }

    ; ShowMore() {{{2
    ShowMore()
    {
        if IsFunc(f := this.ShowInfoFunc) And this.Info
            %f%()
    }

    ; HideMore() {{{2
    HideMore()
    {
        if IsFunc(f:=this.HideInfoFunc) And this.Info
            %f%()
    }
}

; Class __Mode {{{1
Class __Mode
{
    __new(modeName)
    {
        this.name  := modeName
        this.keymapList := []
        this.keymoreList := []
        this.nowaitList := []
        this.modeFunction := ""
    }

    ; SetKeyMap(key, action) {{{2
    SetKeyMap(key, action)
    {
        this.keymapList[key] := action
    }

    ; GetKeyMap(key) {{{2
    GetKeyMap(key)
    {
        return this.keymapList[key]
    }

    ; DelKeyMap(key) {{{2
    DelKeyMap(key)
    {
        this.keymapList[key] := ""
    }

    ; SetNoWait(key, bold) {{{2
    ; 无视TimeOut执行热键
    SetNoWait(key, bold)
    {
        this.nowaitList[key] := bold
    }

    ; GetNoWait(key) {{{2
    GetNoWait(key)
    {
        return this.nowaitList[key]
    }

    ; SetMoreKey(key) {{{2
    SetMoreKey(key)
    {
        this.keymoreList[key] := true
    }

    ; GetMoreKey(key) {{{2
    GetMoreKey(key)
    {
        return this.keymoreList[key]
    }
}

; Class __Action {{{1
Class __Action
{
    ; Action 有几种类型
    ; 0 代表执行Action对应的Label (默认)
    ; 1 代表执行Function的值对应的函数
    ; 2 代表运行CmdLine对应的值
    ; 3 代表发送HotString对应的文本

    __new(Name, Comment)
    {
        this.Name := Name
        this.Comment := Comment
        this.MaxTimes := 0
        this.Type := 0
        this.Function := ""
        this.CmdLine := ""
        this.HotString := ""
    }

    ; SetFunction(Function) {{{2
    ; 设置Action执行的函数名
    SetFunction(Function)
    {
        this.Function := Function
        this.Type := 1
    }

    ; SetCmdLine(CmdLine) {{{2
    ; 设置Action运行的字符串
    SetCmdLine(CmdLine)
    {
        this.CmdLine := CmdLine
        this.Type := 2
    }

    ; SetHotString(HotString) {{{2
    ; 设置Action发送的文本
    SetHotString(HotString)
    {
        this.HotString := HotString
        this.Type := 3
    }

    ; SetMaxTimes(Times) {{{2
    ; 设置最大运行次数
    SetMaxTimes(Times)
    {
        this.MaxTimes := Times
    }

    ; Do(Times=1) {{{2
    ; 执行Action
    Do(Times=0)
    {
        Times := !Times ? 1 : Times
        if this.MaxTimes And (Times > this.MaxTimes)
            Times := this.MaxTimes
        Loop, %Times%
        {
            if this.Type = 0
            {
                if IsLabel(l := this.Name)
                    GoSub, %l%
            }
            else if this.Type = 1
            {
                if IsFunc(f := this.Function)
                    %f%()
            }
            else if this.Type = 2
            {
                c := this.CmdLine
                Run, %cmd%
            }
            else if This.Type = 3
            {
                t := this.HotString
                Send, %t%
            }
        }
    }
}

; Class __Plugin {{{1
Class __Plugin
{
    __new(PluginName)
    {
        this.PluginName := PluginName
        this.Author := ""
        this.Ver := ""
        this.Comment := ""
    }

    ; CheckSub() {{{2
    CheckSub()
    {
        if IsLabel(p := this.PluginName)
        {
            GoSub, %p%
            this.Error := false
        }
        else
            this.Error := true
    }
}

; Class __vimDebug {{{1
Class __vimDebug
{
    __new(key)
    {
        this.mode := key
        if key
        {
            GUI, vimDebug:Destroy
            GUI, vimDebug:+hwnd_vimdebug -Caption +ToolWindow +Border
            GUI, vimDebug:color, 454545, 454545
            GUI, vimDebug:font, s16 cFFFFFF
            GUI, vimDebug:Add, Edit, x-2 y-2 w400 h60 readonly
            GUI, vimDebug:Show, w378 h56 y600
            WinSet, AlwaysOnTop, On, ahk_id %_vimdebug%
        }
        else
        {
            GUI, vimDebug:font, s12
            GUI, vimDebug:Destroy
            GUI, vimDebug:Add, Edit, x10 y10 w400 h300 readonly
            GUI, vimDebug:Add, Edit, x10 y320 w400 h26 readonly
            GUI, vimDebug:Show, w420 h356
        }
    }

    var(obj)
    {
        this.vim := obj
    }

    Set(v)
    {
        winName := this.vim.CheckWin()
        winObj := this.vim.GetWin(winName)
        if winObj.Count
            k := " 热键缓存:" winObj.Count winObj.KeyTemp
        else
             k := " 热键缓存:" winObj.KeyTemp
        GUI, vimDebug:Default
        GUIControl, , Edit1, %v%
        GUIControl, , Edit2, %k%
    }

    Get()
    {
        GUI, vimDebug:Default
        GUIControlGet, v, , Edit1
        return v
    }

    ; Add(v) {{{2
    Add(v)
    {
        b := this.Get()
        if this.mode
            this.Set(b)
        else
            this.Set(v "`n" b)
    }

    ; Clear() {{{2
    Clear()
    {
        this.Set("")
    }
}


Bulk Transfer, Transfer Hotkey, Loop optimizations

;
;Program Name by Noahc3
;Additional Credits
;Built with Autohotkey 1.1.22.09
;Program Version
;
;Source Code available at [Link]
;

val1 = 0
val2 = 0
val3 = 0
val4 = 0
val5 = 0
val6 = 0
val7 = 0
val8 = 0
val9 = 0
val10 = 0
val11 = 0
val12 = 0
val13 = 0
val17 = 0
val31 = 0

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#Include %A_ScriptDir%\libs\csv_lib.ahk
#Include %A_ScriptDir%\libs\tf.ahk
#Include %A_ScriptDir%\libs\zip.ahk

Gui, Main:default

CSV_Load("output.csv", "teamList", ",")

ifnotexist, %A_ScriptDir%\res
{
	FileCreateDir, %A_ScriptDir%\res
	FileCreateDir, %A_ScriptDir%\res\pokemon
	DownloadFile("https://s3.amazonaws.com/noahc3-go/pkmn.zip", A_ScriptDir . "\res\pkmn.zip", false, true)

	Unz(A_ScriptDir . "\res\pkmn.zip", A_ScriptDir . "\res\pokemon")
}
teamLength:=TF_CountLines("output.csv")
tempVar1 = 2
amountList =
resGet = 1
foundTrainer = 0
trLineCheck = 1
trainerLine = 0

while foundTrainer = 0
{
	trVar1 := CSV_ReadCell("teamList", trLineCheck, 1)
	if trVar1 = trainer
	{
		trainerLine = trLineCheck
		amountList = %amountList%Trainer|
		foundTrainer = 1
	}
	else
	{
		trLineCheck += 1
	}
}

tempVar1 = 2
while not tempVar1 = teamLength
{
	tempVar12 := round(((CSV_ReadCell("teamList", tempVar1, 10) + CSV_ReadCell("teamList", tempVar1, 11) + CSV_ReadCell("teamList", tempVar1, 12)) / 45) * 100, 2)

	tempVar2 := CSV_ReadCell("teamList", tempVar1, 2)

	tempVar4 := CSV_ReadCell("teamList", tempVar1, 3)

	amountList = %amountList%%tempVar2%`,   CP: %tempVar4%`,   IV: %tempVar12%`%|

	tempVar1 += 1
}

Gui, Add, DropDownList, x12 y29 w220 h240 AltSubmit gPokeList vPokeList Choose1 HwndPokelisthwnd, %amountList%
Gui, Add, Picture, x32 y69 w100 h100 +Border vPokemonIcon, %A_ScriptDir%\res\pokemon\1.png
Gui, Add, Text, x32 y179 w100 h20 +Center +Border vIDText, ID
Gui, Add, Text, x162 y69 w100 h20 vHPText, HP/HPMAX
Gui, Add, Progress, x162 y89 w180 h10 +Border vHealthBar, 100
Gui, Add, Text, x285 y69 w70 h20 vCP, CP:
Gui, Add, Text, x32 y219 w100 h20 +Center vWeight, Weight (KG):
Gui, Add, Text, x32 y249 w100 h20 +Center vHeight, Height (M):
Gui, Add, Button, x585 y279 w100 h30 gClose, Close
Gui, Add, Button, x465 y279 w100 h30 gTransfer, Transfer
Gui, Add, Button, x345 y279 w100 h30 gBulkTransfer, Bulk Transfer
Gui, Add, Text, x162 y124 w70 h20 vIV, IV's:
Gui, Add, Text, x162 y144 w150 h20 vAIV, Attack:
Gui, Add, Text, x162 y164 w150 h20 vDIV, Defense:
Gui, Add, Text, x162 y184 w150 h20 vHIV, HP:
Gui, Add, Text, x162 y204 w150 h20 vPIV, Perfection:
Gui, Add, Picture, x340 y127 w16 h16 , %A_ScriptDir%\res\img\pokeball.png
Gui, Add, Text, x360 y129 w230 h20 vPokeball, Pokeball Used: Standard
Gui, Add, Text, x360 y159 w230 h20 vFWeight, Full Weight (KG):
Gui, Add, Text, x360 y179 w230 h20 vFHeight, Full Height (M):
Gui, Add, Text, x360 y239 w230 h20 vCPMult, CP Multiplier:
Gui, Add, Text, x360 y219 w230 h20 vUUID, Pokemon UUID:
Gui, Add, Text, x360 y199 w230 h20 vIDBase, ID:
Gui, Add, Text, x360 y69 w170 h20 vMove1, Move 1:
Gui, Add, Text, x530 y69 w170 h20 vMove2, Move 2:
; Generated using SmartGUI Creator 4.0
Gui, Show, h321 w699, Pokemon GO! Team Manager

DefaultDDL()

Return

PokeList:
	Gui, Submit, Nohide

	if PokeList = 1
	{
		DefaultDDL()
	}
	else
	{
		val1 := CSV_ReadCell("teamList", PokeList, 2)
		val2 := CSV_ReadCell("teamList", PokeList, 3)
		val3 := CSV_ReadCell("teamList", PokeList, 4)
		val4 := CSV_ReadCell("teamList", PokeList, 5)
		val5 := CSV_ReadCell("teamList", PokeList, 6)
		val6 := CSV_ReadCell("teamList", PokeList, 7)
		val7 := CSV_ReadCell("teamList", PokeList, 8)
		val8 := CSV_ReadCell("teamList", PokeList, 9)
		val9 := CSV_ReadCell("teamList", PokeList, 10)
		val10 := CSV_ReadCell("teamList", PokeList, 11)
		val11 := CSV_ReadCell("teamList", PokeList, 12)
		val12 := CSV_ReadCell("teamList", PokeList, 13)
		val13 := CSV_ReadCell("teamList", PokeList, 14)
		val17 := CSV_ReadCell("teamList", PokeList, 15)
		val31 := round(((CSV_ReadCell("teamList", PokeList, 10) + CSV_ReadCell("teamList", PokeList, 11) + CSV_ReadCell("teamList", PokeList, 12)) / 45) * 100, 2)

		val14 := getIdenFromName(val1)

		val15 := Round(val7, 2)
		val16 := Round(val8, 2)

		if val13 = ITEM_POKE_BALL
		{
			val13 = Standard
		}
		else if val13 = ITEM_GREAT_BALL
		{
			val13 = Great
		}
		else if val13 = ITEM_ULTRA_BALL
		{
			val13 = Ultra
		}
		else
		{
			val13 = Promo/Unknown
		}

		GuiControl, Text, IDText, %val1%

		GuiControl, show, CP
		GuiControl, show, CPMult
		GuiControl, show, IDBase
		GuiControl, show, Transfer
		GuiControl, show, Bulk Transfer
		GuiControl, show, PIV
		GuiControl, Text, IV, IVs:

		GuiControl, Text, CP, CP: %val2%
		GuiControl, Text, Height, Height (M): %val15%
		GuiControl, Text, Weight, Weight (KG): %val16%
		GuiControl, Text, FHeight, Full Height (M): %val7%
		GuiControl, Text, FWeight, Full Weight (KG): %val8%
		GuiControl, Text, AIV, Attack: %val9%
		GuiControl, Text, DIV, Defense: %val10%
		GuiControl, Text, HIV, HP: %val11%
		GuiControl, Text, PIV, Perfection: %val31%`%
		GuiControl, Text, Pokeball, Pokeball Caught In: %val13%
		GuiControl, Text, Move1, Move 1: %val5%
		GuiControl, Text, Move2, Move 2: %val6%
		GuiControl, Text, HPText, HP: %val3%`/%val4%
		GuiControl, Text, CPMult, CP Multiplier: %val12%
		GuiControl, Text, IDBase, ID: %val14%
		GuiControl, Text, UUID, Pokemon UUID %val17%
		GuiControl, , PokemonIcon, %A_ScriptDir%\res\pokemon\%val14%.png

		healthPercentage := ((val3 / val4)  * 100)

		GuiControl, , HealthBar, %healthPercentage%

		Gui, Submit, Nohide
	}

return

Transfer:

	FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
	run, python "%A_ScriptDir%\libs\py\pogoapi\release.py" --uuid %val17%, %A_ScriptDir%\libs\py\pogoapi

	continue = 0

	While continue = 0
	{
		IfExist, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
		{
			continue = 1
		}
	}

	FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt

	oldPokeList = %PokeList%

	TF_RemoveLines("!output.csv", oldPokeList, oldPokeList)

	CSV_Load("output.csv", "teamList", ",")
	refreshCache()
	GuiControl, Choose, PokeList, |%oldPokeList%

	Gui, Submit, Nohide

	Msgbox, Transfer Finished!
return

BulkTransfer:
	Gui, Bulk:Add, ListBox, x20 y20 w240 h300 AltSubmit vTransferList 8, %amountList%
	Gui, Bulk:Add, Button, x90 y320 w100 h30 gInitBulk, Bulk Transfer
	Gui, Bulk:Show, h400 w280, Bulk Transfer

return

InitBulk:

	MsgBox, 68, Bulk Transfer, This might take some time, would you like to continue?
	IfMsgBox, No
	{
		return
	}

	Gui, Submit, Nohide

	Decrement = 0

	;debug MsgBox, %TransferList%

	transferListStorage := TransferList

	Loop, parse, TransferList, |
	{
		if A_LoopField = 1
		{
			Msgbox, You can't release your trainer! Skipping.
			GoTo skipLoop
		}

		Random, rngsus, 100, 1000

		rngsusPassIn := 750 + rngsus

		sleep, %rngsusPassIn%

		loopFieldStorage := A_LoopField

		uuidField := CSV_ReadCell("teamList", loopFieldStorage, 15)

		;debug MsgBox, %uuidField%

		FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
		run, python "%A_ScriptDir%\libs\py\pogoapi\release.py" --uuid %uuidField%, %A_ScriptDir%\libs\py\pogoapi

		continue = 0

		While continue = 0
		{
			IfExist, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
			{
				continue = 1
			}
		}

		FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt

		Gui, Submit, Nohide

		skipLoop:

	}

	Sort, transferListStorage, R N D|

	Loop, parse, transferListStorage, |
	{
		if A_LoopField = 1
		{
			GoTo skipLoop2
		}
		TF_RemoveLines("!output.csv", A_LoopField, A_LoopField)

		CSV_Load("output.csv", "teamList", ",")
		refreshCache()

		skipLoop2:

	}

	Gui, Bulk:Destroy

	GuiControl, Main:Choose, PokeList, |1

	DefaultDDL()

	MsgBox, Done!

return

Close:
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\info.txt
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\session.txt
	ExitApp
return

^[::
	reload
return

MainGuiClose:
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\info.txt
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\session.txt
	ExitApp
return

BulkGuiClose:
	Gui, Bulk:Destroy
return

DefaultDDL()
{
		val1 := CSV_ReadCell("teamList", 1, 2)
		val2 := CSV_ReadCell("teamList", 1, 3)
		val3 := CSV_ReadCell("teamList", 1, 4)
		val4 := CSV_ReadCell("teamList", 1, 5)
		val5 := CSV_ReadCell("teamList", 1, 6)
		val6 := CSV_ReadCell("teamList", 1, 7)
		val7 := CSV_ReadCell("teamList", 1, 8)
		val8 := CSV_ReadCell("teamList", 1, 9)
		val9 := CSV_ReadCell("teamList", 1, 10)
		val10 := CSV_ReadCell("teamList", 1, 11)
		val11 := CSV_ReadCell("teamList", 1, 12)
		val12 := CSV_ReadCell("teamList", 1, 13)
		val13 := CSV_ReadCell("teamList", 1, 14)
		val17 := CSV_ReadCell("teamList", 1, 15)

		val5 := round(val5, 2)

		GuiControl, Text, IDText, Level: %val6%
		GuiControl, Hide, CP
		GuiControl, Hide, CPMult
		GuiControl, Hide, IDBase
		GuiControl, Hide, Transfer
		GuiControl, Hide, Bulk Transfer
		GuiControl, Hide, PIV
		GuiControl, Text, IV, Stats:
		GuiControl, Text, Weight, Battles Attempted: %val1%
		GuiControl, Text, Height, Battles Won: %val2%
		GuiControl, Text, FHeight, Pokemon Captured: %val10%
		GuiControl, Text, FWeight, Pokemon Encountered: %val11%
		GuiControl, Text, AIV, Pokeballs Thrown: %val9%
		GuiControl, Text, DIV, Stops Visited: %val8%
		GuiControl, Text, HIV, Eggs Hatched: %val3%
		GuiControl, Text, Pokeball, Unique Pokedex Entries %val13%
		GuiControl, Text, Move1, KM Walked: %val5%
		GuiControl, Text, Move2, Prestige Dropped: %val12%
		GuiControl, Text, HPText, XP: %val4%`/%val7%
		GuiControl, Text, UUID, Previous Level XP: %val17%
		GuiControl, , PokemonIcon, %A_ScriptDir%\res\img\trainer_1.png

		val21 := ((val4 / val7) * 100)

		GuiControl, , HealthBar, %val21%
}

^\::
	if Pokelist = 1
	{
		return
	}
	else
	{
		Goto, Transfer
	}
return

refreshCache()
{

	teamLength:=TF_CountLines("output.csv")
	tempVar1 = 2
	amountList =
	resGet = 1
	foundTrainer = 0
	trLineCheck = 1
	trainerLine = 0

	while foundTrainer = 0
	{
		trVar1 := CSV_ReadCell("teamList", trLineCheck, 1)
		if trVar1 = trainer
		{
			trainerLine = trLineCheck
			amountList = %amountList%Trainer|
			foundTrainer = 1
		}
		else
		{
			trLineCheck += 1
		}
	}

	tempVar1 = 2
	while not tempVar1 = teamLength
	{
		tempVar2 := CSV_ReadCell("teamList", tempVar1, 2)

		tempVar4 := CSV_ReadCell("teamList", tempVar1, 3)

		amountList = %amountList%%tempVar2%`, CP: %tempVar4%|

		tempVar1 += 1
	}
	GuiControl, Main: , PokeList, |
	GuiControl, Main: , PokeList, %amountList%
	GuiControl, Bulk: , TransferList, |
	GuiControl, Bulk: , TransferList, %amountList%

	DefaultDDL()
}

;File Downloader by Bruttosozialprodukt
DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) {
    ;Check if the file already exists and if we must not overwrite it
      If (!Overwrite && FileExist(SaveFileAs))
          Return
    ;Check if the user wants a progressbar
      If (UseProgressBar) {
          ;Initialize the WinHttpRequest Object
            WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
          ;Download the headers
            WebRequest.Open("HEAD", UrlToFile)
            WebRequest.Send()
          ;Store the header which holds the file size in a variable:
            FinalSize := WebRequest.GetResponseHeader("Content-Length")
          ;Create the progressbar and the timer
            Progress, H80, , Downloading..., %UrlToFile%
            SetTimer, __UpdateProgressBar, 100
      }
    ;Download the file
      UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
    ;Remove the timer and the progressbar because the download has finished
      If (UseProgressBar) {
          Progress, Off
          SetTimer, __UpdateProgressBar, Off
      }
    Return

    ;The label that updates the progressbar
      __UpdateProgressBar:
          ;Get the current filesize and tick
            CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
            CurrentSizeTick := A_TickCount
          ;Calculate the downloadspeed
            Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000)) . " Kb/s"
          ;Save the current filesize and tick for the next time
            LastSizeTick := CurrentSizeTick
            LastSize := FileOpen(SaveFileAs, "r").Length
          ;Calculate percent done
            PercentDone := Round(CurrentSize/FinalSize*100)
          ;Update the ProgressBar
            Progress, %PercentDone%, %PercentDone%`% Done, Downloading...  (%Speed%), Downloading %SaveFileAs% (%PercentDone%`%)
      Return
}

;oh god dont look man, look for some reason it wouldnt work when i put it in a seperate library and i didnt feel like spending more time on why :P

getIdenFromName(id)
{
	if id = Bulbasaur
	{
	return 1
	}
	else if id = Ivysaur
	{
	return 2
	}
	else if id = Venusaur
	{
	return 3
	}
	else if id = Charmander
	{
	return 4
	}
	else if id = Charmeleon
	{
	return 5
	}
	else if id = Charizard
	{
	return 6
	}
	else if id = Squirtle
	{
	return 7
	}
	else if id = Wartortle
	{
	return 8
	}
	else if id = Blastoise
	{
	return 9
	}
	else if id = Caterpie
	{
	return 10
	}
	else if id = Metapod
	{
	return 11
	}
	else if id = Butterfree
	{
	return 12
	}
	else if id = Weedle
	{
	return "13"
	}
	else if id = Kakuna
	{
	return 14
	}
	else if id = Beedrill
	{
	return 15
	}
	else if id = Pidgey
	{
	return 16
	}
	else if id = Pidgeotto
	{
	return 17
	}
	else if id = Pidgeot
	{
	return 18
	}
	else if id = Rattata
	{
	return 19
	}
	else if id = Raticate
	{
	return 20
	}
	else if id = Spearow
	{
	return 21
	}
	else if id = Fearow
	{
	return 22
	}
	else if id = Ekans
	{
	return 23
	}
	else if id = Arbok
	{
	return 24
	}
	else if id = Pikachu
	{
	return 25
	}
	else if id = Riachu
	{
	return 26
	}
	else if id = Sandshrew
	{
	return 27
	}
	else if id = Sandslash
	{
	return 28
	}
	else if id = Nidoran_female
	{
	return 29
	}
	else if id = Nidorina
	{
	return 30
	}
	else if id = Nidoqueen
	{
	return 31
	}
	else if id = Nidoran_male
	{
	return 32
	}
	else if id = Nidorino
	{
	return 33
	}
	else if id = Nidoking
	{
	return 34
	}
	else if id = Clefairy
	{
	return 35
	}
	else if id = Clefable
	{
	return 36
	}
	else if id = Vulpix
	{
	return 37
	}
	else if id = Ninetales
	{
	return 38
	}
	else if id = Jigglypuff
	{
	return 39
	}
	else if id = Wifflytuff
	{
	return 40
	}
	else if id = Zubat
	{
	return 41
	}
	else if id = Golbat
	{
	return 42
	}
	else if id = Oddish
	{
	return 43
	}
	else if id = Gloom
	{
	return 44
	}
	else if id = Vileplume
	{
	return 45
	}
	else if id = Paras
	{
	return 46
	}
	else if id = Parasect
	{
	return 47
	}
	else if id = Venonat
	{
	return 48
	}
	else if id = Venomoth
	{
	return 49
	}
	else if id = Diglett
	{
	return 50
	}
	else if id = Dugtrio
	{
	return 51
	}
	else if id = Meowth
	{
	return 52
	}
	else if id = Persian
	{
	return 53
	}
	else if id = Psyduck
	{
	return 54
	}
	else if id = Golduck
	{
	return 55
	}
	else if id = Mankey
	{
	return 56
	}
	else if id = Primeape
	{
	return 57
	}
	else if id = Glowlithe
	{
	return 58
	}
	else if id = Arcanine
	{
	return 59
	}
	else if id = Poliwag
	{
	return 60
	}
	else if id = Poliwhirl
	{
	return 61
	}
	else if id = Poliwrath
	{
	return 62
	}
	else if id = Abra
	{
	return 63
	}
	else if id = Kadabra
	{
	return 64
	}
	else if id = Alakazam
	{
	return 65
	}
	else if id = Machop
	{
	return 66
	}
	else if id = Machoke
	{
	return 67
	}
	else if id = Machamp
	{
	return 68
	}
	else if id = Bellsprout
	{
	return 69
	}
	else if id = Weepinbell
	{
	return 70
	}
	else if id = Victreebel
	{
	return 71
	}
	else if id = Tentacool
	{
	return 72
	}
	else if id = Tentacruel
	{
	return 73
	}
	else if id = Geodude
	{
	return 74
	}
	else if id = Graveler
	{
	return 75
	}
	else if id = Golem
	{
	return 76
	}
	else if id = Ponyta
	{
	return 77
	}
	else if id = Rapidash
	{
	return 78
	}
	else if id = Slowpoke
	{
	return 79
	}
	else if id = Slowbro
	{
	return 80
	}
	else if id = Magnemite
	{
	return 81
	}
	else if id = Magneton
	{
	return 82
	}
	else if id = Farfetchd
	{
	return 83
	}
	else if id = Doduo
	{
	return 84
	}
	else if id = Dodrio
	{
	return 85
	}
	else if id = Seel
	{
	return 86
	}
	else if id = Dewgong
	{
	return 87
	}
	else if id = Grimer
	{
	return 88
	}
	else if id = Muk
	{
	return 89
	}
	else if id = Shellder
	{
	return 90
	}
	else if id = Cloyster
	{
	return 91
	}
	else if id = Gastly
	{
	return 92
	}
	else if id = Haunter
	{
	return 93
	}
	else if id = Gengar
	{
	return 94
	}
	else if id = Onic
	{
	return 95
	}
	else if id = Drowzee
	{
	return 96
	}
	else if id = Hypno
	{
	return 97
	}
	else if id = Krabby
	{
	return 98
	}
	else if id = Kingler
	{
	return 99
	}
	else if id = Voltorb
	{
	return 100
	}
	else if id = Electrode
	{
	return 101
	}
	else if id = Exeggcute
	{
	return 102
	}
	else if id = Exeggutor
	{
	return 103
	}
	else if id = Cubone
	{
	return 104
	}
	else if id = Marowak
	{
	return 105
	}
	else if id = Hitmonlee
	{
	return 106
	}
	else if id = Hitmonchan
	{
	return 107
	}
	else if id = Lickitung
	{
	return 108
	}
	else if id = Koffing
	{
	return 109
	}
	else if id = Weezing
	{
	return 110
	}
	else if id = Rhyhorn
	{
	return 111
	}
	else if id = Rhydon
	{
	return 112
	}
	else if id = Chansey
	{
	return 113
	}
	else if id = Tangela
	{
	return 114
	}
	else if id = Kangaskhan
	{
	return 115
	}
	else if id = Horsea
	{
	return 116
	}
	else if id = Seadra
	{
	return 117
	}
	else if id = Goldeen
	{
	return 118
	}
	else if id = Seaking
	{
	return 119
	}
	else if id = Staryu
	{
	return 120
	}
	else if id = Starmie
	{
	return 121
	}
	else if id = Mr Mime
	{
	return 122
	}
	else if id = Scyther
	{
	return 123
	}
	else if id = Jynx
	{
	return 124
	}
	else if id = Electabuzz
	{
	return 125
	}
	else if id = Magmar
	{
	return 126
	}
	else if id = Pinsir
	{
	return 127
	}
	else if id = Tauros
	{
	return 128
	}
	else if id = Magikarp
	{
	return 129
	}
	else if id = Gyrados
	{
	return 130
	}
	else if id = Lapras
	{
	return 131
	}
	else if id = Ditto
	{
	return 132
	}
	else if id = Eevee
	{
	return 133
	}
	else if id = Vaporeon
	{
	return 134
	}
	else if id = Jolteon
	{
	return 135
	}
	else if id = Flareon
	{
	return 136
	}
	else if id = Porygon
	{
	return 137
	}
	else if id = Omanyte
	{
	return 138
	}
	else if id = Omastar
	{
	return 139
	}
	else if id = Kabuto
	{
	return 140
	}
	else if id = Kabutops
	{
	return 141
	}
	else if id = Aerodactyl
	{
	return 142
	}
	else if id = Snorlax
	{
	return 143
	}
	else if id = Articuno
	{
	return 144
	}
	else if id = Zapdos
	{
	return 145
	}
	else if id = Moltres
	{
	return 146
	}
	else if id = Dratini
	{
	return 147
	}
	else if id = Dragonair
	{
	return 148
	}
	else if id = Dragonite
	{
	return 149
	}
	else if id = Mewtwo
	{
	return 150
	}
	else if id = Mew
	{
	return 151
	}
}
return

;
;Program Name by Noahc3
;Additional Credits
;Built with Autohotkey 1.1.22.09
;Program Version
;
;Source Code available at [Link]
;

val1 = 0
val2 = 0
val3 = 0
val4 = 0
val5 = 0
val6 = 0
val7 = 0
val8 = 0
val9 = 0
val10 = 0
val11 = 0
val12 = 0
val13 = 0
val17 = 0

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#Include %A_ScriptDir%\libs\csv_lib.ahk
#Include %A_ScriptDir%\libs\tf.ahk
#Include %A_ScriptDir%\libs\zip.ahk

CSV_Load("output.csv", "teamList", ",")

ifnotexist, %A_ScriptDir%\res
{
	FileCreateDir, %A_ScriptDir%\res
	FileCreateDir, %A_ScriptDir%\res\pokemon
	DownloadFile("https://s3.amazonaws.com/noahc3-go/pkmn.zip", A_ScriptDir . "\res\pkmn.zip", false, true)

	Unz(A_ScriptDir . "\res\pkmn.zip", A_ScriptDir . "\res\pokemon")
}
teamLength:=TF_CountLines("output.csv")
tempVar1 = 2
amountList =
resGet = 1
foundTrainer = 0
trLineCheck = 1
trainerLine = 0

while foundTrainer = 0
{
	trVar1 := CSV_ReadCell("teamList", trLineCheck, 1)
	if trVar1 = trainer
	{
		trainerLine = trLineCheck
		amountList = %amountList%Trainer|
		foundTrainer = 1
	}
	else
	{
		trLineCheck += 1
	}
}

tempVar1 = 2
while not tempVar1 = teamLength
{
	tempVar2 := CSV_ReadCell("teamList", tempVar1, 2)

	tempVar4 := CSV_ReadCell("teamList", tempVar1, 3)

	amountList = %amountList%%tempVar2%`, CP: %tempVar4%|

	tempVar1 += 1
}

Gui, Add, DropDownList, x12 y29 w140 h240 AltSubmit gPokeList vPokeList Choose1 HwndPokelisthwnd, %amountList%
Gui, Add, Picture, x32 y69 w100 h100 +Border vPokemonIcon, %A_ScriptDir%\res\pokemon\1.png
Gui, Add, Text, x32 y179 w100 h20 +Center +Border vIDText, ID
Gui, Add, Text, x162 y69 w100 h20 vHPText, HP/HPMAX
Gui, Add, Progress, x162 y89 w180 h10 +Border vHealthBar, 100
Gui, Add, Text, x285 y69 w70 h20 vCP, CP:
Gui, Add, Text, x32 y219 w100 h20 +Center vWeight, Weight (KG):
Gui, Add, Text, x32 y249 w100 h20 +Center vHeight, Height (M):
Gui, Add, Button, x585 y279 w100 h30 gClose, Close
Gui, Add, Button, x465 y279 w100 h30 gRelease, Release
Gui, Add, Text, x162 y124 w70 h20 vIV, IV's:
Gui, Add, Text, x162 y144 w150 h20 vAIV, Attack:
Gui, Add, Text, x162 y164 w150 h20 vDIV, Defense:
Gui, Add, Text, x162 y184 w150 h20 vHIV, HP:
Gui, Add, Picture, x340 y127 w16 h16 , %A_ScriptDir%\res\img\pokeball.png
Gui, Add, Text, x360 y129 w230 h20 vPokeball, Pokeball Used: Standard
Gui, Add, Text, x360 y159 w230 h20 vFWeight, Full Weight (KG):
Gui, Add, Text, x360 y179 w230 h20 vFHeight, Full Height (M):
Gui, Add, Text, x360 y239 w230 h20 vCPMult, CP Multiplier:
Gui, Add, Text, x360 y219 w230 h20 vUUID, Pokemon UUID:
Gui, Add, Text, x360 y199 w230 h20 vIDBase, ID:
Gui, Add, Text, x360 y69 w170 h20 vMove1, Move 1:
Gui, Add, Text, x530 y69 w170 h20 vMove2, Move 2:
; Generated using SmartGUI Creator 4.0
Gui, Show, h321 w699, Pokemon GO! Team Manager

DefaultDDL()

Return

PokeList:
	Gui, Submit, Nohide

	if PokeList = 1
	{
		DefaultDDL()
	}
	else
	{
		val1 := CSV_ReadCell("teamList", PokeList, 2)
		val2 := CSV_ReadCell("teamList", PokeList, 3)
		val3 := CSV_ReadCell("teamList", PokeList, 4)
		val4 := CSV_ReadCell("teamList", PokeList, 5)
		val5 := CSV_ReadCell("teamList", PokeList, 6)
		val6 := CSV_ReadCell("teamList", PokeList, 7)
		val7 := CSV_ReadCell("teamList", PokeList, 8)
		val8 := CSV_ReadCell("teamList", PokeList, 9)
		val9 := CSV_ReadCell("teamList", PokeList, 10)
		val10 := CSV_ReadCell("teamList", PokeList, 11)
		val11 := CSV_ReadCell("teamList", PokeList, 12)
		val12 := CSV_ReadCell("teamList", PokeList, 13)
		val13 := CSV_ReadCell("teamList", PokeList, 14)
		val17 := CSV_ReadCell("teamList", PokeList, 15)

		val14 := getIdenFromName(val1)

		val15 := Round(val7, 2)
		val16 := Round(val8, 2)

		if val13 = ITEM_POKE_BALL
		{
			val13 = Standard
		}
		else if val13 = ITEM_GREAT_BALL
		{
			val13 = Great
		}
		else if val13 = ITEM_ULTRA_BALL
		{
			val13 = Ultra
		}
		else
		{
			val13 = Promo/Unknown
		}

		GuiControl, Text, IDText, %val1%

		GuiControl, show, CP
		GuiControl, show, CPMult
		GuiControl, show, IDBase
		GuiControl, show, Release
		GuiControl, Text, IV, IVs:

		GuiControl, Text, CP, CP: %val2%
		GuiControl, Text, Height, Height (M): %val15%
		GuiControl, Text, Weight, Weight (KG): %val16%
		GuiControl, Text, FHeight, Full Height (M): %val7%
		GuiControl, Text, FWeight, Full Weight (KG): %val8%
		GuiControl, Text, AIV, Attack: %val9%
		GuiControl, Text, DIV, Defense: %val10%
		GuiControl, Text, HIV, HP: %val11%
		GuiControl, Text, Pokeball, Pokeball Caught In: %val13%
		GuiControl, Text, Move1, Move 1: %val5%
		GuiControl, Text, Move2, Move 2: %val6%
		GuiControl, Text, HPText, HP: %val3%`/%val4%
		GuiControl, Text, CPMult, CP Multiplier: %val12%
		GuiControl, Text, IDBase, ID: %val14%
		GuiControl, Text, UUID, Pokemon UUID %val17%
		GuiControl, , PokemonIcon, %A_ScriptDir%\res\pokemon\%val14%.png

		healthPercentage := ((val3 / val4)  * 100)

		GuiControl, , HealthBar, %healthPercentage%

		Gui, Submit, Nohide
	}

return

Release:

	FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
	run, python "%A_ScriptDir%\libs\py\pogoapi\release.py" --uuid %val17%, %A_ScriptDir%\libs\py\pogoapi

	continue = 0

	While continue = 0
	{
		IfExist, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt
		{
			continue = 1
		}
	}

	FileDelete, %A_ScriptDir%\libs\py\pogoapi\doneRelease.txt

	oldPokeList = %PokeList%

	TF_RemoveLines("!output.csv", oldPokeList, oldPokeList)

	CSV_Load("output.csv", "teamList", ",")
	refreshCache()
	GuiControl, Choose, PokeList, |%oldPokeList%

	Gui, Submit, Nohide

	Msgbox, Release Finished!
return

Close:
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\info.txt
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\session.txt
	ExitApp
return

^[::
	reload
return

GuiClose:
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\info.txt
	FileDelete, %A_ScriptDir%\libs\py\pogoapi\session.txt
	ExitApp
return

DefaultDDL()
{
	val1 := CSV_ReadCell("teamList", 1, 2)
		val2 := CSV_ReadCell("teamList", 1, 3)
		val3 := CSV_ReadCell("teamList", 1, 4)
		val4 := CSV_ReadCell("teamList", 1, 5)
		val5 := CSV_ReadCell("teamList", 1, 6)
		val6 := CSV_ReadCell("teamList", 1, 7)
		val7 := CSV_ReadCell("teamList", 1, 8)
		val8 := CSV_ReadCell("teamList", 1, 9)
		val9 := CSV_ReadCell("teamList", 1, 10)
		val10 := CSV_ReadCell("teamList", 1, 11)
		val11 := CSV_ReadCell("teamList", 1, 12)
		val12 := CSV_ReadCell("teamList", 1, 13)
		val13 := CSV_ReadCell("teamList", 1, 14)
		val17 := CSV_ReadCell("teamList", 1, 15)

		val5 := round(val5, 2)

		GuiControl, Text, IDText, Level: %val6%
		GuiControl, Hide, CP
		GuiControl, Hide, CPMult
		GuiControl, Hide, IDBase
		GuiControl, Hide, Release
		GuiControl, Text, IV, Stats:
		GuiControl, Text, Weight, Battles Attempted: %val1%
		GuiControl, Text, Height, Battles Won: %val2%
		GuiControl, Text, FHeight, Pokemon Captured: %val10%
		GuiControl, Text, FWeight, Pokemon Encountered: %val11%
		GuiControl, Text, AIV, Pokeballs Thrown: %val9%
		GuiControl, Text, DIV, Stops Visited: %val8%
		GuiControl, Text, HIV, Eggs Hatched: %val3%
		GuiControl, Text, Pokeball, Unique Pokedex Entries %val13%
		GuiControl, Text, Move1, KM Walked: %val5%
		GuiControl, Text, Move2, Prestige Dropped: %val12%
		GuiControl, Text, HPText, XP: %val4%`/%val7%
		GuiControl, Text, UUID, Previous Level XP: %val17%
		GuiControl, , PokemonIcon, %A_ScriptDir%\res\img\trainer_1.png

		val21 := ((val4 / val7) * 100)

		GuiControl, , HealthBar, %val21%
}

refreshCache()
{

	teamLength:=TF_CountLines("output.csv")
	tempVar1 = 2
	amountList =
	resGet = 1
	foundTrainer = 0
	trLineCheck = 1
	trainerLine = 0

	while foundTrainer = 0
	{
		trVar1 := CSV_ReadCell("teamList", trLineCheck, 1)
		if trVar1 = trainer
		{
			trainerLine = trLineCheck
			amountList = %amountList%Trainer|
			foundTrainer = 1
		}
		else
		{
			trLineCheck += 1
		}
	}

	tempVar1 = 2
	while not tempVar1 = teamLength
	{
		tempVar2 := CSV_ReadCell("teamList", tempVar1, 2)

		tempVar4 := CSV_ReadCell("teamList", tempVar1, 3)

		amountList = %amountList%%tempVar2%`, CP: %tempVar4%|

		tempVar1 += 1
	}
	GuiControl, , PokeList, |
	GuiControl, , PokeList, %amountList%

	DefaultDDL()
}

;File Downloader by Bruttosozialprodukt
DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True) {
    ;Check if the file already exists and if we must not overwrite it
      If (!Overwrite && FileExist(SaveFileAs))
          Return
    ;Check if the user wants a progressbar
      If (UseProgressBar) {
          ;Initialize the WinHttpRequest Object
            WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
          ;Download the headers
            WebRequest.Open("HEAD", UrlToFile)
            WebRequest.Send()
          ;Store the header which holds the file size in a variable:
            FinalSize := WebRequest.GetResponseHeader("Content-Length")
          ;Create the progressbar and the timer
            Progress, H80, , Downloading..., %UrlToFile%
            SetTimer, __UpdateProgressBar, 100
      }
    ;Download the file
      UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
    ;Remove the timer and the progressbar because the download has finished
      If (UseProgressBar) {
          Progress, Off
          SetTimer, __UpdateProgressBar, Off
      }
    Return

    ;The label that updates the progressbar
      __UpdateProgressBar:
          ;Get the current filesize and tick
            CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
            CurrentSizeTick := A_TickCount
          ;Calculate the downloadspeed
            Speed := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000)) . " Kb/s"
          ;Save the current filesize and tick for the next time
            LastSizeTick := CurrentSizeTick
            LastSize := FileOpen(SaveFileAs, "r").Length
          ;Calculate percent done
            PercentDone := Round(CurrentSize/FinalSize*100)
          ;Update the ProgressBar
            Progress, %PercentDone%, %PercentDone%`% Done, Downloading...  (%Speed%), Downloading %SaveFileAs% (%PercentDone%`%)
      Return
}

;oh god dont look man, look for some reason it wouldnt work when i put it in a seperate library and i didnt feel like spending more time on why :P

getIdenFromName(id)
{
	if id = Bulbasaur
	{
	return 1
	}
	else if id = Ivysaur
	{
	return 2
	}
	else if id = Venusaur
	{
	return 3
	}
	else if id = Charmander
	{
	return 4
	}
	else if id = Charmeleon
	{
	return 5
	}
	else if id = Charizard
	{
	return 6
	}
	else if id = Squirtle
	{
	return 7
	}
	else if id = Wartortle
	{
	return 8
	}
	else if id = Blastoise
	{
	return 9
	}
	else if id = Caterpie
	{
	return 10
	}
	else if id = Metapod
	{
	return 11
	}
	else if id = Butterfree
	{
	return 12
	}
	else if id = Weedle
	{
	return "13"
	}
	else if id = Kakuna
	{
	return 14
	}
	else if id = Beedrill
	{
	return 15
	}
	else if id = Pidgey
	{
	return 16
	}
	else if id = Pidgeotto
	{
	return 17
	}
	else if id = Pidgeot
	{
	return 18
	}
	else if id = Rattata
	{
	return 19
	}
	else if id = Raticate
	{
	return 20
	}
	else if id = Spearow
	{
	return 21
	}
	else if id = Fearow
	{
	return 22
	}
	else if id = Ekans
	{
	return 23
	}
	else if id = Arbok
	{
	return 24
	}
	else if id = Pikachu
	{
	return 25
	}
	else if id = Riachu
	{
	return 26
	}
	else if id = Sandshrew
	{
	return 27
	}
	else if id = Sandslash
	{
	return 28
	}
	else if id = Nidoran_female
	{
	return 29
	}
	else if id = Nidorina
	{
	return 30
	}
	else if id = Nidoqueen
	{
	return 31
	}
	else if id = Nidoran_male
	{
	return 32
	}
	else if id = Nidorino
	{
	return 33
	}
	else if id = Nidoking
	{
	return 34
	}
	else if id = Clefairy
	{
	return 35
	}
	else if id = Clefable
	{
	return 36
	}
	else if id = Vulpix
	{
	return 37
	}
	else if id = Ninetales
	{
	return 38
	}
	else if id = Jigglypuff
	{
	return 39
	}
	else if id = Wifflytuff
	{
	return 40
	}
	else if id = Zubat
	{
	return 41
	}
	else if id = Golbat
	{
	return 42
	}
	else if id = Oddish
	{
	return 43
	}
	else if id = Gloom
	{
	return 44
	}
	else if id = Vileplume
	{
	return 45
	}
	else if id = Paras
	{
	return 46
	}
	else if id = Parasect
	{
	return 47
	}
	else if id = Venonat
	{
	return 48
	}
	else if id = Venomoth
	{
	return 49
	}
	else if id = Diglett
	{
	return 50
	}
	else if id = Dugtrio
	{
	return 51
	}
	else if id = Meowth
	{
	return 52
	}
	else if id = Persian
	{
	return 53
	}
	else if id = Psyduck
	{
	return 54
	}
	else if id = Golduck
	{
	return 55
	}
	else if id = Mankey
	{
	return 56
	}
	else if id = Primeape
	{
	return 57
	}
	else if id = Glowlithe
	{
	return 58
	}
	else if id = Arcanine
	{
	return 59
	}
	else if id = Poliwag
	{
	return 60
	}
	else if id = Poliwhirl
	{
	return 61
	}
	else if id = Poliwrath
	{
	return 62
	}
	else if id = Abra
	{
	return 63
	}
	else if id = Kadabra
	{
	return 64
	}
	else if id = Alakazam
	{
	return 65
	}
	else if id = Machop
	{
	return 66
	}
	else if id = Machoke
	{
	return 67
	}
	else if id = Machamp
	{
	return 68
	}
	else if id = Bellsprout
	{
	return 69
	}
	else if id = Weepinbell
	{
	return 70
	}
	else if id = Victreebel
	{
	return 71
	}
	else if id = Tentacool
	{
	return 72
	}
	else if id = Tentacruel
	{
	return 73
	}
	else if id = Geodude
	{
	return 74
	}
	else if id = Graveler
	{
	return 75
	}
	else if id = Golem
	{
	return 76
	}
	else if id = Ponyta
	{
	return 77
	}
	else if id = Rapidash
	{
	return 78
	}
	else if id = Slowpoke
	{
	return 79
	}
	else if id = Slowbro
	{
	return 80
	}
	else if id = Magnemite
	{
	return 81
	}
	else if id = Magneton
	{
	return 82
	}
	else if id = Farfetchd
	{
	return 83
	}
	else if id = Doduo
	{
	return 84
	}
	else if id = Dodrio
	{
	return 85
	}
	else if id = Seel
	{
	return 86
	}
	else if id = Dewgong
	{
	return 87
	}
	else if id = Grimer
	{
	return 88
	}
	else if id = Muk
	{
	return 89
	}
	else if id = Shellder
	{
	return 90
	}
	else if id = Cloyster
	{
	return 91
	}
	else if id = Gastly
	{
	return 92
	}
	else if id = Haunter
	{
	return 93
	}
	else if id = Gengar
	{
	return 94
	}
	else if id = Onic
	{
	return 95
	}
	else if id = Drowzee
	{
	return 96
	}
	else if id = Hypno
	{
	return 97
	}
	else if id = Krabby
	{
	return 98
	}
	else if id = Kingler
	{
	return 99
	}
	else if id = Voltorb
	{
	return 100
	}
	else if id = Electrode
	{
	return 101
	}
	else if id = Exeggcute
	{
	return 102
	}
	else if id = Exeggutor
	{
	return 103
	}
	else if id = Cubone
	{
	return 104
	}
	else if id = Marowak
	{
	return 105
	}
	else if id = Hitmonlee
	{
	return 106
	}
	else if id = Hitmonchan
	{
	return 107
	}
	else if id = Lickitung
	{
	return 108
	}
	else if id = Koffing
	{
	return 109
	}
	else if id = Weezing
	{
	return 110
	}
	else if id = Rhyhorn
	{
	return 111
	}
	else if id = Rhydon
	{
	return 112
	}
	else if id = Chansey
	{
	return 113
	}
	else if id = Tangela
	{
	return 114
	}
	else if id = Kangaskhan
	{
	return 115
	}
	else if id = Horsea
	{
	return 116
	}
	else if id = Seadra
	{
	return 117
	}
	else if id = Goldeen
	{
	return 118
	}
	else if id = Seaking
	{
	return 119
	}
	else if id = Staryu
	{
	return 120
	}
	else if id = Starmie
	{
	return 121
	}
	else if id = Mr Mime
	{
	return 122
	}
	else if id = Scyther
	{
	return 123
	}
	else if id = Jynx
	{
	return 124
	}
	else if id = Electabuzz
	{
	return 125
	}
	else if id = Magmar
	{
	return 126
	}
	else if id = Pinsir
	{
	return 127
	}
	else if id = Tauros
	{
	return 128
	}
	else if id = Magikarp
	{
	return 129
	}
	else if id = Gyrados
	{
	return 130
	}
	else if id = Lapras
	{
	return 131
	}
	else if id = Ditto
	{
	return 132
	}
	else if id = Eevee
	{
	return 133
	}
	else if id = Vaporeon
	{
	return 134
	}
	else if id = Jolteon
	{
	return 135
	}
	else if id = Flareon
	{
	return 136
	}
	else if id = Porygon
	{
	return 137
	}
	else if id = Omanyte
	{
	return 138
	}
	else if id = Omastar
	{
	return 139
	}
	else if id = Kabuto
	{
	return 140
	}
	else if id = Kabutops
	{
	return 141
	}
	else if id = Aerodactyl
	{
	return 142
	}
	else if id = Snorlax
	{
	return 143
	}
	else if id = Articuno
	{
	return 144
	}
	else if id = Zapdos
	{
	return 145
	}
	else if id = Moltres
	{
	return 146
	}
	else if id = Dratini
	{
	return 147
	}
	else if id = Dragonair
	{
	return 148
	}
	else if id = Dragonite
	{
	return 149
	}
	else if id = Mewtwo
	{
	return 150
	}
	else if id = Mew
	{
	return 151
	}
}
return