import numpy as np
import pyautogui
import pydirectinput
import time
# import keyboard
import cv2

Xc=int(1920/2)
Yc=int(1080/2)

def row(x,y,dx=0,dy=0,button='right',delay=0.2):
    '''
    在 (x,y) 處，按下滑鼠 button 鍵後拖曳 dx,dy
    '''
    pydirectinput.mouseDown(x,y,button=button);time.sleep(delay)
    pydirectinput.moveTo(x+dx,y+dy);    time.sleep(delay)
    pydirectinput.mouseUp(button=button)
    
def zoom2max():
    '''
    拉最遠並把視角放到頭頂
    '''
    global Xc,Yc
    for i in range(10):    pyautogui.scroll(-500)
    row(Xc,Yc,dy=50)
    row(Xc,Yc,dy=50)
    
def click(x=None,y=None,repeat=1,delay=0):
    '''
    點擊 x,y 重複 repeat 次，每次延遲 delay 秒
    '''
    try:
        if x==None:
            for i in range(repeat):pydirectinput.click();time.sleep(delay)
        else:
            for i in range(repeat):pydirectinput.click(x,y);pydirectinput.click(x+1,y+1);time.sleep(delay)
    except:print("except while click()...")
    
def slide(key='down',repeat=1):
    '''
    按q滑行，由 key 指定方向， 重複repeat次
    '''
    for i in range(repeat):
        pydirectinput.keyDown(key)
        pydirectinput.press('q')
        pydirectinput.keyUp(key)
    
def keyDown(key,duration=2):
    '''
    按下 key , 等待 duration 秒後放開
    '''
    pydirectinput.keyDown(key);time.sleep(duration);pydirectinput.keyUp(key)
    
def press(key,repeat=1,delay=0):
    '''
    按 key ，重覆repeat次，每次等的delay秒
    '''
    for i in range(repeat):pydirectinput.press(key);time.sleep(delay)
    
def reset(delay=8):
    '''
    重設色角色 esc + r + enter
    '''
    pydirectinput.press('esc');time.sleep(1)
    pydirectinput.press('r');time.sleep(1)
    pydirectinput.press('enter')
    time.sleep(delay)
    
def findColors(color,image=[],tolorance=0):
    '''
    給定 image ，在上面找到和 color 相近顏色的座標
    並回傳座標陣列，tolorance 為容忍範圍
    '''
    if len(image)==0:image = pyautogui.screenshot()
    image=np.array(image)
    a=np.array(image)
    b=np.array(color)
    dist = np.linalg.norm(a-b, axis=-1)
    return np.argwhere(dist <= tolorance)

def checkColorByXY(x,y,image=[],color=(241,234,41),
                   color_tolorance=25,
                   XY_tolorance=8):
    '''
    找出螢幕上所有顏色類似 color 的像素所在位置，看是否有接近 (x,y) 的
    若有則回傳真
    '''
    if len(image)==0:image = pyautogui.screenshot()
    image=np.array(image)
    ps=findColors(color,image,color_tolorance)
    if len(ps)>0:
        print('目標y,x:',ps[0])
        dist = np.linalg.norm(ps-np.array([y,x]), axis=-1)
    #     print("===============")
    #     print(dist)
        ps = np.argwhere(dist <= XY_tolorance)
        if len(ps)>0:return True
        else :return False
    return False
    
def findColorsInSize(color,image=[],tolorance=0,size=300):
    '''
    給定 image ，在上面找到和 color 相近顏色的座標
    並回傳座標陣列，tolorance 為容忍範圍
    size為上下左右搜與範圍
    '''
    global Xc,Yc
    if len(image)==0:image = pyautogui.screenshot()
    image=np.array(image)
    a=image[Yc-size:Yc+size,Xc-size:Xc+size]
    b=np.array(color)
    dist = np.linalg.norm(a-b, axis=-1)
    base = np.array([Yc-size,Xc-size])
    ret = np.argwhere(dist <= tolorance) + base
    return ret



def findNearestColor(color,tolorance=0):
    '''
    找到離角色(螢幕中心)最近的指定顏色 color
    '''
    global Xc,Yc
    a = findColors(color,tolorance=tolorance)
    if len(a)==0:return -1,-1
    else:
        b = np.array([Yc,Xc])
        i = np.argmin(np.linalg.norm(a-b,axis=-1))
        y,x = a[i]
        return x,y

def instinctOn(p1=(932,902),p2=(985,910)):
    '''
    檢查是否開啟見聞色，落未開啟啟見聞色就按下e開啟它
    '''
    img = np.array(pyautogui.screenshot())
    L,T=p1
    R,B=p2
    ps=findColors((124, 216, 239),img[T:B,L:R],tolorance=30)
    if len(ps)<10:press('e')
    
    
def getMission(p1=(1400,560),p2=(1400,510)):
    '''
    取得任務
    p1是選擇任務的座標
    p2是按「確認」的座標
    '''
    global Xc,Yc
#     1433,566
    click(Xc,Yc,delay=2)
    click(p1[0],p1[1]);time.sleep(2)
#     click(1448,562);time.sleep(2)
    row(Xc,Yc)
    click(p2[0],p2[1]);time.sleep(2)
    click(p2[0],p2[1]);time.sleep(2)
    
def aimEnemy():
    '''
    在見聞色下找到最近的敵人瞄準一下
    '''
    x,y = findNearestColor((255,0,0))
    if x>0:
        print(f'瞄準：{x},{y}',)
        row(x,y,dx=1,delay=0)
#         click(x,y);
        return True
    return False

def shotEnemy(a='4',b='',c='1'):
    '''
    在見聞色下找到最近的敵人
    開 a 欄位做射擊,a='1'or'2'or'3'or'4'
    使用 b 招,     b='z'or'x'or'c'or'v'
    切換回 c 欄位   c='1'or'2'or'3'or'4'
    '''
    x,y = findNearestColor((255,0,0))
    if x>0:
        print(f'射擊：{x},{y}',)
        if a!='':press(a);
        row(x,y,dx=1,delay=0)
        click(x,y);
        if b!='':press(b)
        if c!='':press(c)
        return True
    return False

def isComplete(targetImgPath='goal.png',p1=(740,596)):
    '''
    檢查螢幕中是否有 goal.png 來判斷任務是否完成
    若任務已完成就開啟邏盤，p1為縮小對話框的座標
    '''
    try:
        x,y=pyautogui.locateCenterOnScreen(targetImgPath,confidence=0.92)
        click(x,y,delay=1)
        click(p1[0],p1[1])
        print('mission complete!')
        return True
    except:return False
    
def close2Color(color=(241, 234, 41),size=300,tolorance=25,
                distTH=13,
                offsetX=0,offsetY=45):
    '''
    以角色為中心搜與方圓 size內的指定顏色(color)
    並接近指定顏色所在位置
    offsetX:X方向偏移值
    offsetY:Y方向偏移值
    '''
    global Xc,Yc
    while True:
        ps=findColorsInSize(color, tolorance=tolorance,size=size)
        if(len(ps)>0):
            y,x=ps[0]
            y+=offsetY
            x+=offsetX
            print(f'接近目標顏色{color} 位置：({x},{y})')
            if x>Xc+distTH:press('d')
            elif x<Xc-distTH:press('a')
            elif y>Yc+distTH:press('s')
            elif y<Yc-distTH:press('w')
            else:break
        else:print(f'找不到指定顏定{color}');break
        
def getXYDist(x,y,color):#1590,918
    pix = np.array(pyautogui.pixel(x,y))
    dist = np.linalg.norm(pix-np.array(color),axis=-1)
    print(f"於({x},{y})處 pix={pix}和目標顏色{color}距離={dist}")
    return dist
#=============================================        
def goEnemy():
    global isGetMission
    zoom2max()
    if checkColorByXY(x=553,y=656):
        #背對問號
        keyDown('left',0.5)
        slide('w',2);slide('a',2)
        close2Color(color=(241, 234, 41))
        if isGetMission:getMission(p1=(1400,510))
        isGetMission = False
        slide('d',5)
        slide('s',12)
    else:
        #面向問號
        slide('w',4);slide('d',1)
        if checkColorByXY(x=1124,y=93):
            slide('w',3);slide('d',1)
            close2Color(color=(241, 234, 41))
            getMission(p1=(1400,510))
            print('1')
            slide('a',5);slide('s',3);slide('a',9)
        elif checkColorByXY(x=1132,y=96):
            slide('w',3);slide('d',1)
            close2Color(color=(241, 234, 41))
            getMission(p1=(1400,510))
            print('2')
            slide('a',5);slide('s',2);slide('a',8)
        else:
            close2Color(color=(241, 234, 41))
            getMission(p1=(1400,510))
            slide('a',12)
            slide('w',2)
            print('3')


def fight():
    for i in range(33):
        print('fight:',i)
        instinctOn()
        time.sleep(0.6)
        shotEnemy(a='', b='v', c='')
        if aimEnemy():
            if getXYDist(1590,918,(180,180,180))>50:
                press('v')
            else:press('4');click();press('2')
        press('e')
        for j in range(150):click()
        if isComplete(targetImgPath='goal.png', p1=(740,596)):
            return True
    return False
    
isGetMission = False
def work():
    global isGetMission
    while True:
        reset()
        if getXYDist(925,962,(131, 226, 247))>30:press('2')
        goEnemy()
        isGetMission = fight()
        
        
if __name__ == '__main__':
    
    click(Xc,Yc)
    work()



# (x,y)=(1587,918),pixel=(79, 80, 84)
# (x,y)=(1593,918),pixel=(185, 186, 187)

# print(isComplete(targetImgPath='goal.png', p1=(740,596)))

# ps=findColors((255,0,0))
# print(ps)

