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

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

import os
import time
import requests

from lxml import etree

from core_server import BaseServer
from errors import ServerError, NetError
from parameter import CONFIG, ItemConfig
from utilites import get_api_data, get_url_headers, download

class Selenoid(BaseServer):
	def capability(self):
		return [("selenoid:options", CONFIG.SELENOID_OPTIONS)]
	
	def is_match(self):
		try:
			data = get_api_data(self.executor, timeout=CONFIG.REMOTE_TIMEOUT)
		except NetError:
			raise ServerError("Не удалось подключится к: "+self.executor)
		except Exception:
			return False
		if data:
			return "selenoid" in str(data).lower()
		return False
	
	def get_download_file(self, name, download_dir):
		"""
		Дожидается завершения скачивания файла.
		Сохраняет скаченный файл в локальный каталог и возвращает путь к скаченному файлу.
		Если файла нет, то ошибка FileNotFoundError
		"""
		path = os.path.join(download_dir, name)
		if not os.path.isfile(path):
			self.get_size_download_file(name)
			url = "/".join(["http:/", self.executor, "download", self.session_id, name])
			try:
				is_downloaded = download(url, download_dir, name, timeout=CONFIG.DOWNLOAD_TIMEOUT)
			except NetError:
				raise FileNotFoundError(url)
			if is_downloaded:
				return path
			raise FileNotFoundError(url)
		return path
	
	def get_size_download_file(self, name):
		"""
		Дожидается завершения скачивания файла и возвращает его размер
		Если файла нет, то ошибка FileNotFoundError
		"""
		url = "/".join(["http:/", self.executor, "download", self.session_id, name])
		t0 = time.time()
		while time.time() < t0 + CONFIG.DOWNLOAD_TIMEOUT:
			headers = get_url_headers(url, CONFIG.REMOTE_TIMEOUT)
			if headers and int(headers["content-length"]) > 0:
				return int(headers["content-length"])
			time.sleep(CONFIG.WAIT_DELAY)
		raise FileNotFoundError(name)
	
	def del_download_file(self, name):
		"""
		Удаляет скаченный файл на сервере
		"""
		requests.delete(
			"/".join(["http:/", self.executor, "download", self.session_id, name])
			, timeout=CONFIG.REMOTE_TIMEOUT
		)
	
	def download_files(self):
		"""
		Возвращает список скаченных файлов
		"""
		res = requests.get(
			"/".join(["http:/", self.executor, "download", self.session_id])
			, timeout=CONFIG.REMOTE_TIMEOUT
		)
		if 100 < res.status_code < 300:
			return list({ x.text for x in etree.fromstring(res.content) if x.tag == "a" })
		return []
	
	def get_links(self):
		"""
		Возвращает словарь ссылок на файлы видео и логов
		"""
		res = {}
		if CONFIG.SELENOID_OPTIONS.get("enableLog"):
			res["log"]   = "/".join(["http:/", self.executor, "logs", self.session_id + ".log"])
		if CONFIG.SELENOID_OPTIONS.get("enableVideo"):
			res["video"] = "/".join(["http:/", self.executor, "video", CONFIG.SELENOID_OPTIONS.get("videoName", self.session_id) + ".mp4"])
		return res

ItemConfig.registrator(
	ItemConfig("SELENOID_OPTIONS", dict, {}, "SELENOID: Параметры selenoid")
)
