import pyautogui
import ctypes
import time
import win32gui, win32con, win32process
from pyvda import VirtualDesktop, get_virtual_desktops
import subprocess
import asyncio

class WhaleTranslator:
    def __init__(self, app, logger, secret_mode=True, vd_mode=False):
        self.app = app
        self.logger = logger
        self.vd_mode = vd_mode
        self.newtab = "about:newtab"
        self.whale_pid = None
        isSecret = secret_mode

        if isSecret:
            self.whale_window_name = "새 시크릿 탭 - Whale"
        else:
            self.whale_window_name = "새 탭 - Whale"

        self.whale_hwnd = None

    async def start_whale_browser(self):
        """비동기 브라우저 시작 및 가상 데스크탑 처리"""
        if self.vd_mode:
            self.ensure_virtual_desktop_2_exists()  # 가상 데스크탑 2 생성

        # Whale 브라우저 실행
        whale_path = r"C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe"
        process = subprocess.Popen([whale_path, '--incognito'])
        self.whale_pid = process.pid
        self.logger.debug(f"Whale 브라우저 실행, PID: {self.whale_pid}")

        await asyncio.sleep(2)  # 브라우저가 실행될 때까지 대기

        hwnd = win32gui.FindWindow(None, self.whale_window_name)
        if hwnd:
            win32gui.ShowWindow(hwnd, win32con.SW_NORMAL)
            win32gui.SetWindowPos(hwnd, None, 0, 0, 1920, 1080, win32con.SWP_NOZORDER)
        else:
            self.logger.debug("Whale 창을 찾을 수 없습니다.")

        if self.vd_mode:
            self.return_to_virtual_desktop_1()  # 가상 데스크탑 1로 복귀
    
    def find_whale_window(self):
        """프로세스 ID를 기반으로 웨일 창 핸들을 찾는 메서드"""
        if not self.whale_hwnd:
            self.whale_hwnd = self.find_window_by_pid(self.whale_pid)
        return self.whale_hwnd

    def find_window_by_pid(self, pid):
        """프로세스 ID를 기반으로 창 핸들을 찾는 메서드"""
        def enum_windows_callback(hwnd, pid_list):
            tid, found_pid = win32process.GetWindowThreadProcessId(hwnd)
            if found_pid == pid:
                pid_list.append(hwnd)

        hwnd_list = []
        win32gui.EnumWindows(enum_windows_callback, hwnd_list)
        return hwnd_list[0] if hwnd_list else None

    # def find_whale_window(self):
    #     """웨일 창 핸들을 찾는 메서드"""
    #     if not self.whale_hwnd:
    #         self.whale_hwnd = self.find_window_by_title(self.whale_window_name)
    #     return self.whale_hwnd

    # def find_window_by_title(self, window_name):
    #     def enum_windows_callback(hwnd, result):
    #         if win32gui.IsWindowVisible(hwnd) and window_name in win32gui.GetWindowText(hwnd):
    #             result.append(hwnd)
    #     result = []
    #     win32gui.EnumWindows(enum_windows_callback, result)
    #     return result[0] if result else None

    def ensure_virtual_desktop_2_exists(self):
        """가상 데스크톱 2가 존재하는지 확인하고, 없으면 생성"""
        try:
            # 현재 활성화된 가상 데스크톱 수 확인
            desktops = get_virtual_desktops()
            number_of_desktops = len(desktops)

            # 가상 데스크톱 2가 존재하지 않으면 생성
            if number_of_desktops < 2:
                pyautogui.hotkey('win', 'ctrl', 'd')  # 새 가상데스크탑 생성
                self.logger.debug("가상 데스크톱 2가 생성되었습니다.")
                time.sleep(1)
            else:
                self.switch_to_virtual_desktop_2()
                self.close_whale_window_if_exists()
                self.logger.debug("가상 데스크톱 2가 이미 존재합니다.")
        
        except Exception as e:
            self.logger.debug(f"가상 데스크톱 확인/생성 중 오류 발생: {e}", exc_info=True)

    def switch_to_whale(self):
        """웨일로 포커스 전환"""
        
        if self.whale_hwnd:
            win32gui.ShowWindow(self.whale_hwnd, win32con.SW_RESTORE)
            win32gui.SetForegroundWindow(self.whale_hwnd)
            self.logger.debug('크롬 창으로 포커스 이동.')
        else:
            self.logger.debug('크롬 창을 찾을 수 없습니다.')

    def switch_to_virtual_desktop_2(self):
        """가상 데스크톱 2로 전환"""
        try:
            VirtualDesktop(2).go()
            self.logger.debug("가상 데스크톱 2로 전환되었습니다.")
            time.sleep(0.3)
        except Exception as e:
            self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}", exc_info=True)

    def return_to_virtual_desktop_1(self):
        """가상 데스크톱 1로 복귀"""
        try:
            VirtualDesktop(1).go()
            self.logger.debug("가상 데스크톱 1로 전환되었습니다.")
            time.sleep(0.3)
        except Exception as e:
            self.logger.debug(f"가상 데스크톱 전환 중 오류 발생: {e}", exc_info=True)

    async def translate_image(self, url, path=None):
        
        if self.vd_mode:
            self.switch_to_virtual_desktop_2()
            
        if not self.find_whale_window():  # 웨일 창을 찾지 못할 경우
            self.logger.debug("웨일 창을 찾을 수 없습니다. 새 웨일 창을 생성합니다.")
            await self.create_and_update_whale_window()  # 새 창 생성

        if self.find_whale_window():
            win32gui.ShowWindow(self.whale_hwnd, win32con.SW_RESTORE)  # 웨일 창 활성화
            win32gui.SetForegroundWindow(self.whale_hwnd)

            pyautogui.moveTo(960,580)      # 마우스 센터로 이동
            
            pyautogui.hotkey('ctrl', 'l')  # 웨일 브라우저의 주소창으로 이동
            self.enter_url(url)
            await asyncio.sleep(1)         # 페이지 로딩 대기

            pyautogui.rightClick()
            await asyncio.sleep(0.2)       # 페이지 로딩 대기
            pyautogui.press('r')           # 번역 클릭
            await asyncio.sleep(7)         # 페이지 로딩 대기

            pyautogui.rightClick()
            await asyncio.sleep(0.2)       # 페이지 로딩 대기
            pyautogui.press('c')           # 번역된 이미지 클립보드에 복사
            pyautogui.hotkey('ctrl', 'l')  # 새 탭으로 이동
            pyautogui.typewrite(self.newtab)  # URL을 입력
            self.enter_url(self.newtab)
            self.logger.debug(f'번역 완료: {url}')

            if self.vd_mode:
                self.return_to_virtual_desktop_1()

            # 경로를 인자로 받을경우 해당경로에 파일 저장
            if path:
                pass # 클립보드의 이미지를 path의 파일로 저장하고 저장경로를 리턴하는 메서드
                    # path에는 현재 폴더의 tmp_img폴더에 상품명-옵션명 형태로 제공됨
        else:
            self.logger.debug('웨일 창을 찾을 수 없습니다.')

    async def create_and_update_whale_window(self):
        """
        웨일 창을 찾지 못했을 경우 새 웨일 창을 생성하고 핸들을 업데이트하는 메서드.
        """
        self.logger.debug("웨일 창을 찾지 못해 새 웨일 창을 생성합니다.")
        
        # 웨일 브라우저 실행
        whale_path = r"C:\\Program Files\\Naver\\Naver Whale\\Application\\whale.exe"
        process = subprocess.Popen([whale_path, '--incognito'])
        self.whale_pid = process.pid
        self.logger.debug(f"새 웨일 브라우저 실행, PID: {self.whale_pid}")
        
        await asyncio.sleep(2)  # 브라우저가 실행될 때까지 대기

        # 창 핸들 업데이트
        self.whale_hwnd = self.find_whale_window()
        
        if self.whale_hwnd:
            self.logger.debug(f"새로 생성된 웨일 창 핸들: {self.whale_hwnd}")
            win32gui.ShowWindow(self.whale_hwnd, win32con.SW_NORMAL)
            win32gui.SetWindowPos(self.whale_hwnd, None, 0, 0, 1920, 1080, win32con.SWP_NOZORDER)
        else:
            self.logger.debug("새로 생성된 웨일 창을 찾지 못했습니다.")

    def switch_language(self):
        # Shift 키 누름
        pyautogui.keyDown('shift')
        
        # 0.1초 대기 후 Alt 키 누름
        time.sleep(1)
        pyautogui.keyDown('alt')
        
        # 0.5초 대기
        time.sleep(1)
        
        # Alt 키 해제
        pyautogui.keyUp('alt')
        
        # Shift 키 해제
        pyautogui.keyUp('shift')


    def set_input_language(self, lang='EN'):
        # 윈도우에서 입력 언어를 변경하는 코드
        # lang='EN' 또는 lang='KR'을 설정 가능
        user32 = ctypes.WinDLL('user32', use_last_error=True)
        if lang == 'EN':
            # 영어로 변경
            user32.LoadKeyboardLayoutW('00000409', 1)
        elif lang == 'KR':
            # 한글로 변경
            user32.LoadKeyboardLayoutW('00000412', 1)

    def enter_url(self, url):

        # 주소창에 URL 입력하기 전에 영어로 변경
        # self.set_input_language('EN')

        # await asyncio.sleep(0.5)  # 입력 모드 전환 후 잠시 대기

        # 주소창으로 이동 후 URL 입력
        pyautogui.hotkey('ctrl', 'l')  # 주소창으로 이동
        time.sleep(0.5)
        pyautogui.typewrite(url)  # URL 입력
        pyautogui.press('enter',)  # Enter 키 입력
        time.sleep(1)  # 페이지 로딩 대기
        

    def close_whale_window_if_exists(self):
        """웨일 브라우저 창을 프로세스 ID(pid)로 찾아 종료"""
        try:
            if not self.whale_pid:
                self.logger.debug("웨일 프로세스 ID가 설정되지 않았습니다.")
                return
            
            def enum_windows_callback(hwnd, result):
                _, found_pid = win32process.GetWindowThreadProcessId(hwnd)
                if found_pid == self.whale_pid and win32gui.IsWindowVisible(hwnd):
                    result.append(hwnd)

            result = []
            win32gui.EnumWindows(enum_windows_callback, result)

            if result:
                hwnd = result[0]
                self.logger.debug(f"웨일 창을 찾았습니다. 핸들: {hwnd}. 종료 중...")
                win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)  # 창을 종료하는 메시지 전송
                time.sleep(1)
                self.logger.debug(f"웨일 창이 성공적으로 종료되었습니다.")
            else:
                self.logger.debug("웨일 창을 찾을 수 없습니다.")

        except Exception as e:
            self.logger.error(f"웨일 창을 종료하는 중 오류 발생: {e}", exc_info=True)

    async def close_all_virtual_desktops(self):
        """모든 가상 데스크톱을 종료"""
        try:
            desktops = get_virtual_desktops()
            number_of_desktops = len(desktops)

            # 가상 데스크톱이 1개 이상일 때만 종료
            while number_of_desktops > 1:
                self.close_whale_window_if_exists()  # 웨일 브라우저 창이 있으면 종료
                pyautogui.hotkey('win', 'ctrl', 'f4')  # 현재 가상 데스크톱 닫기
                time.sleep(1)  # 각 데스크톱 닫기 사이에 짧은 대기시간 추가
                desktops = get_virtual_desktops()
                number_of_desktops = len(desktops)
                self.logger.debug(f"남은 가상 데스크톱 수: {number_of_desktops}")

            self.logger.debug("모든 가상 데스크톱이 종료되었습니다.")

        except Exception as e:
            self.logger.debug(f"가상 데스크톱 종료 중 오류 발생: {e}", exc_info=True)
