"""
1、等待元素可见
2、查找元素
3、点击操作：等待 - 查找 - 点击
4、输入操作：等待 - 查找 - 输入
5、获取元素文本：等待 - 查找 - 获取文本
6、获取元素属性：等待 - 查找 - 获取属性值

节省代码量、记录日志、失败截图

7、窗口切换 -- 让新窗口出现，获取所有句柄，切换到新窗口。
"""
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.remote.webdriver import WebDriver
import os
import time
import pyautogui

from Common.my_logger import logger
from Common.handle_path import screenshot_dir


class Basepage:

    def __init__(self, driver: WebDriver):
        self.driver = driver

    # 等待元素可见
    def wait_ele_visible(self, locator, page_action, timeout=10, poll_frequency=0.5):
        """
        :param locator:元素定位，例：(By.XPATH, '//input[@class="login-username"]')
        :param page_action:页面动作，在进行什么操作
        :param timeout:超时时间
        :param poll_frequency:轮循时间
        """
        logger.info("在 {} 行为，等待元素：{} 可见。".format(page_action, locator))
        try:
            start = time.time()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.visibility_of_element_located(locator))
        except:
            # 输出到日志
            logger.exception("等待元素可见失败！")
            # 失败截取当前页面
            self.get_page_img(page_action)
            raise
        else:
            end = time.time()
            logger.info("等待耗时为：{}".format(end - start))

    # 等待元素存在
    def wait_page_contains_element(self, locator, page_action, timeout=20, poll_frequency=0.5):
        logger.info("在 {} 行为，等待元素：{} 存在。".format(page_action, locator))
        try:
            start = time.time()
            WebDriverWait(self.driver, timeout, poll_frequency).until(EC.presence_of_element_located(locator))
        except:
            # 输出到日志
            logger.exception("等待元素存在失败！")
            # 失败截取当前页面
            self.get_page_img(page_action)
            raise
        else:
            end = time.time()
            logger.info("等待耗时为：{}".format(end - start))

    # 先等待 再查找
    def get_element(self, locator, page_action, timeout=20, poll_frequency=0.5, wait=None):
        # 等待元素存在或者可见
        if wait:
            self.wait_page_contains_element(locator, page_action, timeout, poll_frequency)
        else:
            self.wait_ele_visible(locator, page_action, timeout, poll_frequency)

        logger.info("在 {} 行为，查找元素：{}".format(page_action, locator))
        try:
            ele = self.driver.find_element(*locator)
        except:
            # 输出到日志
            logger.exception("查找元素失败！")
            # 失败截取当前页面
            self.get_page_img(page_action)
            raise
        else:
            return ele

    # 点击操作
    def click_element(self, locator, page_action, timeout=20, poll_frequency=0.5, wait=None):
        # 等待 - 查找
        ele = self.get_element(locator, page_action, timeout, poll_frequency, wait)
        # 点击
        logger.info("在 {} 行为，点击元素：{}".format(page_action, locator))
        try:
            ele.click()
        except:
            logger.exception("点击元素失败！")
            self.get_page_img(page_action)
            raise

    # 输入操作
    def input_text(self, locator, page_action, value, timeout=20, poll_frequency=0.5):
        # 等待 - 查找
        ele = self.get_element(locator, page_action, timeout, poll_frequency)
        logger.info("在 {} 行为，给元素：{} 输入文本值：{}".format(page_action, locator, value))
        try:
            ele.clear()
            ele.send_keys(value)
        except:
            logger.exception("元素输入文本失败！")
            self.get_page_img(page_action)
            raise

    # 获取文本操作
    def get_text(self, locator, page_action, timeout=20, poll_frequency=0.5):
        ele = self.get_element(locator, page_action, timeout, poll_frequency)
        logger.info("在 {} 行为，获取元素：{} 的文本值".format(page_action, locator))
        try:
            return ele.text
        except:
            logger.exception("获取元素文本失败！")
            self.get_page_img(page_action)
            raise

    # 获取元素属性操作
    def get_attribute(self, locator, page_action, value, timeout=20, poll_frequency=0.5):
        ele = self.get_element(locator, page_action, timeout, poll_frequency)
        logger.info("在 {} 行为，获取元素：{} {} 的属性值".format(page_action, locator, value))
        try:
            return ele.get_attribute(value)
        except:
            logger.exception("获取元素属性失败！")
            self.get_page_img(page_action)
            raise

    # 刷新页面
    def refresh_page(self, page_action):
        try:
            self.driver.refresh()
        except:
            logger.exception("刷新页面失败！")
            self.get_page_img(page_action)
            raise

    # 页面回退
    def back_page(self, page_action):
        try:
            self.driver.back()
        except:
            logger.exception("页面回退失败！")
            self.get_page_img(page_action)
            raise

    # 窗口跳转
    def switch_window(self):
        # 等待一下
        time.sleep(1)
        try:
            # 获取所有的句柄
            wins = self.driver.window_handles
            self.driver.switch_to.window(wins[-1])
        except:
            logger.exception("窗口跳转失败！")
            raise

    # 失败截图
    def get_page_img(self, page_action):
        # 命令规范: {XX页面_XX操作}_截图时间.png
        cur_time = time.strftime('%Y-%m-%d %H-%M-%S', time.localtime())
        file_path = os.path.join(screenshot_dir, "{} {}.png".format(page_action, cur_time))
        self.driver.save_screenshot(file_path)
        logger.info("截图保存在：{}".format(file_path))

    # 文件上传
    def uploadFile(self, locator, page_action, filepath):
        '''
        系统上传文件,各个系统通用
        locator: 上传文件按钮定位表达式
        page_action：页面动作，在进行什么操作
        filepath：上传文件的路径
        '''
        try:
            self.click_element(locator, page_action)
            time.sleep(3)
            pyautogui.write(filepath)  # 输入文件绝对路径
            time.sleep(2)
            pyautogui.press('enter', presses=2)  # 按2次回车键（按2次是为了防止出错）
        except Exception as e:
            logger.exception("上传文件操作失败！")
            self.get_page_img(page_action)
            raise

    # 实现按钮存在但无法点击问题，移动到目标元素处
    def notClick_exist(self, locator, page_action, wait):
        element = self.get_element(locator, page_action, wait=wait)
        ActionChains(self.driver).click(element).perform()


if __name__ == '__main__':
    from selenium import webdriver
    from time import sleep
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    #
    # driver = webdriver.Chrome()
    # base = Basepage(driver)
    # driver.get("http://www.baidu.com")
    # # 等待输入框可见
    # loc = ("id", "kw")
    # loc_button = ("id", "su")
    # loc_text = (By.XPATH, '//div[@id="s-top-left"]/a[3]')
    #
    # at = base.get_attribute(loc_button, "百度首页_点击搜索按钮", "value")
    # print(at)
    # te = base.get_text(loc_text, "百度首页_获取文本")
    # print(te)
    #
    # base.input_text(loc, "百度首页_输入搜索内容", "selenium webdriver")
    # base.click_element(loc_button, "百度首页_点击搜索按钮")
    #
    # sleep(7)
    # driver.quit()

    # driver = webdriver.Chrome()
    # base = Basepage(driver)
    # driver.get('https://www.yzktw.com.cn/post/919529.html')
    # driver.maximize_window()
    # driver.execute_script("document.documentElement.scrollTop=10000")
    # # 等待1秒
    # time.sleep(1)
    # ele = driver.find_element(By.ID, 'upload-btn')
    # ActionChains(driver).click(ele).perform()
    # time.sleep(3)
    # pyautogui.write(r'G:\web_framework\document\7.jpeg')
    # time.sleep(2)
    # pyautogui.press('enter', presses=2)  # 按2次回车键（按2次是为了防止出错）
    # time.sleep(10)

    driver = webdriver.Chrome()
    base = Basepage(driver)
    driver.get('https://www.baidu.com')

    a = (By.XPATH, '//input[@id="kw"]')
    b = (By.XPATH, '//input[@id="su"]')

    base.input_text(a, "输入框", "python")
    time.sleep(5)
    base.refresh_page("刷新页面")
    base.input_text(a, "输入框", "python")
    time.sleep(5)
    base.click_element(b, "点击按钮")
    base.back_page("回退页面")
    # c = (By.XPATH, '//div[@class="wbrjf67"]')
    # base.click_element(c, "打开新窗口")
    # time.sleep(5)
    # base.switch_window()
    # d = (By.XPATH, '//a[text()="快速安装"]')
    # base.get_element(d, "确定窗口跳转是否成功！")
    # base.click_element(d, "点击操作")
    # time.sleep(5)
    driver.quit()


