#!/usr/bin/python3
# coding: utf-8

#################################################################
#
# Copyright (C) ИП Пуляев Григорий Васильевич, 2024
# email: rodegast@xmail.ru
# telegram: t.me/kybyc_meta_test
#
# Расширение добавляет поддержку браузера Yandex Browser
# в платформу автоматизированного тестирования Meta Test.
#
# Этот файл НЕ является частью платформы Meta Test.
# Лицензия расширения - Apache License 2.0
# https://www.apache.org/licenses/LICENSE-2.0
#
#################################################################

import os
from functools import lru_cache

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService

from errors import InstallError, NetError
from core_brower import WebBrowser, install
from parameter import CONFIG, LOG_LEVEL, ItemConfig
from utilites import get_api_json, get_platform, rMkDir, x_path

__all__ = (
	"get_yandexdriver",
)

@lru_cache
def get_url_yandexdriver(version, platform):
	"""
	Возввращает URL на скачивание драйвера
	"""
	endpoint = "https://api.github.com/repos/yandex/YandexDriver/releases"
	try:
		data = get_api_json(
			endpoint
			, headers={"Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}
			, timeout=CONFIG.REMOTE_TIMEOUT
		)
	except NetError:
		raise InstallError("Не удалось получить информацию о YandexDriver:\n "+endpoint)
	except Exception as err:
		raise InstallError(err)
	if data:
		for x in [ x for x in data if x["name"] == version +"-stable" ]:
			for y in x["assets"]:
				try:
					if platform == "linux64" and y["name"].endswith("linux.zip") or \
					   platform == "mac-x64" and y["name"].endswith("mac.zip") or \
					   platform == "win64"   and y["name"].endswith("win.zip"):
						return y["browser_download_url"]
				except KeyError:
					continue
	raise InstallError("Невозможно получить yandexdriver для версии "+version)

class Yandex(WebBrowser):
	@lru_cache
	def installed_versions(self):
		"""
		Возвращает описание локально установленных браузеров
		{"версия браузера": "путь к исполняемому файлу"}
		"""
		platform = get_platform()
		if platform == "mac-x64":
			return self.mac_installed_version("/Applications/Yandex.app/Contents/MacOS/Yandex")
		elif platform == "linux64":
			return self.linux_installed_version(("yandex_browser", "yandex-browser-stable", "yandex-browser"))
		return self.windows_installed_version((
			r"PROGRAMFILES\\Yandex\\YandexBrowser\\Application\\browser.exe"
			, r"PROGRAMFILES(X86)\\Yandex\\YandexBrowser\\Application\\browser.exe"
			, r"LOCALAPPDATA\\Yandex\\YandexBrowser\\Application\\browser.exe"
			, r"PROGRAMW6432\\Yandex\\YandexBrowser\\Application\\browser.exe"
		))
	
	def make_options(self):
		options = webdriver.ChromeOptions()
		options.page_load_strategy = CONFIG.PAGE_LOAD_STRATEGY.lower()
		options.add_experimental_option("excludeSwitches", ["enable-logging", "enable-automation"])
		options.add_experimental_option("useAutomationExtension", False)
		
		platform = get_platform()
		if platform == "linux64":
			user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 YaBrowser/%s.0 Safari/537.36"
		elif platform == "mac-x64":
			user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 YaBrowser/%s.0 Safari/537.36"
		else:
			user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 YaBrowser/%s.0 Safari/537.36"
		options.add_argument("--user-agent='%s'"%(user_agent % self.short_version))
		
		options.add_argument("--no-sandbox")
		options.add_argument("--no-crash-upload")
		options.add_argument("--allow-insecure-localhost")
		options.add_argument("--ignore-certificate-errors")
		options.add_argument("--reduce-security-for-testing")
		options.add_argument("--allow-running-insecure-content")
		options.add_argument("--ignore-urlfetcher-cert-requests")
		
		options.add_argument("--disable-infobars")
		options.add_argument("--disable-extensions")
		options.add_argument("--disable-notifications")
		options.add_argument("--disable-dev-shm-usage")
		options.add_argument("--disable-popup-blocking")
		options.add_argument("--disable-crash-reporter")
		options.add_argument("--disable-smooth-scrolling")
		options.add_argument("--disable-plugins-discovery")
		options.add_argument("--disable-oopr-debug-crash-dump")
		options.add_argument("--disable-blink-features=AutomationControlled")
		
		if self.enable_logs:
			options.set_capability("goog:loggingPrefs", {
				LOG_TYPES.BROWSER.lower()      : CONFIG.LOG_LEVEL
				, LOG_TYPES.CLIENT.lower()     : CONFIG.LOG_LEVEL
				, LOG_TYPES.DRIVER.lower()     : CONFIG.LOG_LEVEL
				, LOG_TYPES.SERVER.lower()     : CONFIG.LOG_LEVEL
				, LOG_TYPES.PROFILER.lower()   : CONFIG.LOG_LEVEL
				, LOG_TYPES.PERFORMANCE.lower(): CONFIG.LOG_LEVEL
			})
		
		prefs = {
			"intl.accept_languages": CONFIG.BROWSER_LANG
			, "intl.selected_languages": CONFIG.BROWSER_LANG
		}
		if self.download_dir:
			options.add_argument("--disable-features=InsecureDownloadWarnings")
			prefs.update({
				"profile.default_content_settings.popups": 0
				, "download.prompt_for_download": False
				, "download.directory_upgrade": True
				, "disable-popup-blocking": True
				, "safebrowsing.enabled": True
				, "plugins.always_open_pdf_externally": True
				, "plugins.plugins_disabled": ["Chrome PDF Viewer"]
				, "profile.default_content_setting_values.automatic_downloads": 1
			})
			options.enable_downloads = True
			if not self.is_local_browser:
				options.set_capability("se:downloadsEnabled", True)
			else:
				prefs["download.default_directory"] = self.download_dir
		else:
			options.enable_downloads = False
			options.set_capability("se:downloadsEnabled", False)
			if CONFIG.INCOGNITO:
				options.add_argument("incognito")
				options.add_argument("--disable-blink-features=AutomationControlled")
		options.add_experimental_option("prefs", prefs)
		
		if self.cache_dir and not CONFIG.INCOGNITO:
			options.add_argument("--disk-cache-dir="+self.cache_dir)
		else:
			options.add_argument("--disable-cache")
			options.add_argument("--disk-cache-size=0")
			options.add_argument("--media-cache-size=0")
			options.add_argument("--disable-application-cache")
		if CONFIG.PROXY:
			options.add_argument("--proxy-server="+CONFIG.PROXY)
		if self.profile_dir:
			options.add_argument("--user-data-dir="+self.profile_dir)
			options.add_argument("--allow-profiles-outside-user-dir")
			options.add_argument("--enable-profile-shortcut-manager")
			options.add_argument("--profile-directory=Default")
		if CONFIG.HEADLESS:
			options.add_argument("--headless=new")
			
			options.add_argument("--silent")
			options.add_argument("--disable-gpu")
			options.add_argument("--hide-scrollbars")
			options.add_argument("--disable-low-res-tiling")
			options.add_argument("--disable-renderer-backgrounding")
			options.add_argument("--disable-background-timer-throttling")
			options.add_argument("--disable-backgrounding-occluded-windows")
			options.add_argument("--disable-client-side-phishing-detection")
		if self.is_local_browser:
			if self.binary_location:
				options.binary_location = self.binary_location
		else:
			options.set_capability("browserName", self.browser_name)
			options.set_capability("browserVersion", self.version)
			options.set_capability("acceptInsecureCerts", True)
		return options
	
	def make_service(self):
		"""
		Возвращает объект обслуживания
		"""
		return ChromeService(self.driver_path)
	
	@property
	def web_driver_class(self):
		"""
		Возвращает класс веб-драйвера
		"""
		return webdriver.Chrome
	
	@property
	def browser_name(self):
		"""
		Возвращает имя браузера
		"""
		return "yandex"
	
	@property
	def short_version(self):
		"""
		Возвращает сокращённую версию браузера
		"""
		return ".".join(self.version.split(".")[:3])
	
	@property
	def driver_path(self):
		"""
		Возвращает путь к файлу драйвера
		"""
		if not CONFIG.YANDEX_DRIVER_PATH:
			platform     = get_platform()
			install_path = os.path.join(CONFIG.BROWSERS_DIR, self.browser_name, self.short_version)
			driver_file  = os.path.join(install_path, "yandexdriver")
			if platform == "win64":
				driver_file += ".exe"
			if not os.path.isfile(driver_file):
				rMkDir(os.path.join(CONFIG.BROWSERS_DIR, self.browser_name))
				url = get_url_yandexdriver(self.short_version, platform)
				if platform == "win64":
					install(url, install_path, {"yandexdriver.exe": driver_file})
				else:
					install(url, install_path, {"yandexdriver": driver_file})
			CONFIG.YANDEX_DRIVER_PATH = x_path(driver_file)
		return CONFIG.YANDEX_DRIVER_PATH
	
	@property
	def user_local_path(self):
		"""
		Путь к исполняемому файлу браузера указанный пользователем
		"""
		return CONFIG.YANDEX_LOCAL_PATH
	
	@property
	def user_version(self):
		"""
		Версия браузера которую указал пользователь в качестве используемой
		"""
		return CONFIG.YANDEX_VERSION

ItemConfig.registrator(
	ItemConfig("YANDEX_DRIVER_PATH",  str, "", "YANDEX: Путь к файлу драйвера yandexdriver")
	, ItemConfig("YANDEX_VERSION",    str, "", "YANDEX: Версия yandex_browser")
	, ItemConfig("YANDEX_LOCAL_PATH", str, "", "YANDEX: Путь к исполняемому файлу yandex_browser")
)
