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

#################################################################
#
# Copyright (C) ИП Пуляев Григорий Васильевич, 2024
# email: rodegast@xmail.ru
# telegram: t.me/kybyc_meta_test
#
# Расширение добавляет поддержку браузера Microsoft Edge
# в платформу автоматизированного тестирования 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.edge.service import Service as EdgeService

from errors import InstallError, NetError
from core_brower import WebBrowser, install
from parameter import CONFIG, LOG_TYPES, ItemConfig
from utilites import Version, get_platform, get_api_data, x_path

os.environ["MSEDGEDRIVER_TELEMETRY_OPTOUT"] = "1"
# https://learn.microsoft.com/ru-ru/microsoft-edge/webdriver-chromium/capabilities-edge-options

class Edge(WebBrowser):
	@lru_cache
	def installed_versions(self):
		"""
		Возвращает описание локально установленных браузеров
		{"версия браузера": "путь к исполняемому файлу"}
		"""
		platform = get_platform()
		if platform == "mac-x64":
			return self.mac_installed_version("/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge")
		elif platform == "linux64":
			return self.linux_installed_version((
				"microsoft-edge", "microsoft-edge-stable", "microsoft-edge-beta", "microsoft-edge-dev"
			))
		return self.windows_installed_version((
			r"PROGRAMFILES\\Microsoft\\Edge\\Application\\msedge.exe"
			, r"PROGRAMFILES(X86)\\Microsoft\\Edge\\Application\\msedge.exe"
			, r"PROGRAMFILES\\Microsoft\\Edge Beta\\Application\\msedge.exe"
			, r"PROGRAMFILES(X86)\\Microsoft\\Edge Beta\\Application\\msedge.exe"
			, r"LOCALAPPDATA\\Microsoft\\Edge Beta\\Application\\msedge.exe"
			, r"PROGRAMFILES\\Microsoft\\Edge Dev\\Application\\msedge.exe"
			, r"PROGRAMFILES(X86)\\Microsoft\\Edge Dev\\Application\\msedge.exe"
			, r"LOCALAPPDATA\\Microsoft\\Edge Dev\\Application\\msedge.exe"
			, r"LOCALAPPDATA\\Microsoft\\Edge SxS\\Application\\msedge.exe"
		))
	
	def make_options(self):
		"""
		Возвращает объект конфигурации драйвера
		"""
		options = webdriver.EdgeOptions()
		options.use_chromium = True
		options.page_load_strategy = CONFIG.PAGE_LOAD_STRATEGY.lower()
		
		platform = get_platform()
		if platform == "linux64":
			user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0 Safari/537.36 Edg/%s"
		elif platform == "mac-x64":
			user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0 Safari/537.36 Edg/%s"
		else:
			user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/%s.0 Safari/537.36 Edg/%s"
		options.add_argument("user-agent="+user_agent % (self.short_version, self.version));
		
		options.add_argument("--no-sandbox")
		options.add_argument("--no-first-run")
		options.add_argument("--disable-infobars")
		options.add_argument("--no-default-browser-check")
		options.add_argument("--window-size=%i,%i"%CONFIG.PAGE_SIZE)
		options.add_experimental_option("excludeSwitches", [
			"disable-popup-blocking", "enable-automation"
		])
		
		prefs = {
			"intl.accept_languages": CONFIG.BROWSER_LANG
			, "intl.selected_languages": CONFIG.BROWSER_LANG
		}
		if self.download_dir:
			options.add_argument("--disable-popup-blocking")
			options.add_argument("--disable-features=DownloadUI")
			options.add_argument("--disable-search-engine-choice-screen")
			options.add_argument("--disable-features=msSmartScreenProtection")
			options.add_argument("--safebrowsing-disable-download-protection")
			options.add_argument("--disable-features=DownloadBubble,DownloadBubbleV2")
			
			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
				, "browser.show_hub_popup_on_download_start": False
				, "safebrowsing.disable_download_protection": True
				, "plugins.plugins_disabled": ["Chrome PDF Viewer"]
				, "profile.default_content_setting_values.notifications": 2
				, "profile.default_content_setting_values.automatic_downloads": 1
				, "profile.content_settings.exceptions.automatic_downloads.*.setting": 2
				, "profile.content_settings.pattern_pairs.*,*.multiple-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 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 self.enable_logs:
			options.set_capability("ms: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
			})
		
		if CONFIG.HEADLESS:
			options.add_argument("headless")
		
		if self.is_local_browser:
			if self.binary_location:
				options.binary_location = self.binary_location
		else:
			options.set_capability("acceptInsecureCerts", True)
			options.set_capability("browserVersion", self.version)
			options.set_capability("browserName", self.browser_name)
		if self.version:
			options.browser_version = self.version
		return options
	
	def make_service(self):
		"""
		Возвращает объект обслуживания
		"""
		args = []
		if CONFIG.EDGE_DRIVER_PATH:
			args.append("--disable-build-check")
		return EdgeService(executable_path=self.driver_path, service_args=args)
	
	@property
	def web_driver_class(self):
		"""
		Возвращает класс веб-драйвера
		"""
		return webdriver.Edge
	
	@property
	def browser_name(self):
		"""
		Возвращает имя браузера
		"""
		return "edge"
	
	@property
	def driver_path(self):
		"""
		Возвращает путь к файлу драйвера
		"""
		# https://edgeupdates.microsoft.com/api/products
		if not CONFIG.EDGE_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, "msedgedriver")
			if platform == "win64":
				driver_file += ".exe"
			if not os.path.isfile(driver_file):
				if platform == "linux64":
					url = "https://msedgedriver.microsoft.com/LATEST_RELEASE_%s_LINUX"
				elif platform == "mac-64":
					url = "https://msedgedriver.microsoft.com/LATEST_RELEASE_%s_MACOS"
				else:
					url = "https://msedgedriver.microsoft.com/LATEST_RELEASE_%s_WINDOWS"
				endpoint = url%self.major_version
				try:
					lates_version = get_api_data(endpoint, timeout=CONFIG.REMOTE_TIMEOUT)
				except NetError:
					raise InstallError("Не удалось получить информацию о msedgedriver:\n "+endpoint)
				if lates_version:
					lates_version = lates_version.decode("utf-16").strip()
					url = "https://msedgedriver.microsoft.com/%s/edgedriver_%s.zip"%(lates_version, platform)
				else:
					url = "https://msedgedriver.microsoft.com/%s.0/edgedriver_%s.zip"%(self.short_version, platform)
				
				if platform == "win64":
					install(url, install_path, {"msedgedriver.exe": driver_file})
				else:
					install(url, install_path, {"msedgedriver": driver_file})
			CONFIG.EDGE_DRIVER_PATH = x_path(driver_file)
		return CONFIG.EDGE_DRIVER_PATH
	
	@property
	def user_local_path(self):
		"""
		Путь к исполняемому файлу браузера указанный пользователем
		"""
		platform = get_platform()
		if platform == "linux64":
			return CONFIG.EDGE_LOCAL_PATH or "/opt/microsoft/msedge/msedge"
		return CONFIG.EDGE_LOCAL_PATH
	
	@property
	def enable_logs(self):
		"""
		Возвращает True если поддерживается логирование
		"""
		return True
	
	@property
	def user_version(self):
		"""
		Версия браузера которую указал пользователь в качестве используемой
		"""
		return CONFIG.EDGE_VERSION
	
	@property
	def short_version(self):
		"""
		Возвращает сокращённую версию браузера
		"""
		return ".".join(self._version.split(".")[:3])

ItemConfig.registrator(
	ItemConfig("EDGE_VERSION", str, "", "EDGE: Версия edge")
	, ItemConfig("EDGE_LOCAL_PATH", str, "", "EDGE: Путь к исполняемому файлу edge")
	, ItemConfig("EDGE_DRIVER_PATH", str, "", "EDGE: Путь к файлу драйвера msedgedriver")
)
