"""Module contains functionality that parses main page for RedHat vulnerabilities."""

import time

import lxml
import lxml.etree
from selenium import webdriver
from selenium.common.exceptions import WebDriverException, NoSuchElementException
from selenium.webdriver.chrome.options import Options
from cve_connector.vendor_cve.implementation.parsers.general_and_format_parsers\
    .html_parser import HtmlParser
from cve_connector.vendor_cve.implementation.utilities.utility_functions import string_to_date


class RedHatMainPageParser(HtmlParser):
    """
    Class providing functionality for parsing RedHat main page.
    """
    def __init__(self, url, logger, from_date=None, to_date=None):
        super().__init__(url, from_date, to_date)
        self.date_format = '%d %b %Y'  # 20 Apr 2018
        self.driver = None
        self.entry_added = False
        self.last_added = False
        self.first_cve_on_page = ''
        self.logger = logger
        try:
            self.load_content()
        except ValueError:
            self.logger.error('Unable to load content from {0}'.format(self.url))

    def get_content_from_ulr(self):
        """
        Gets and returns content from URL.

        :return: content
        """
        if not self.url:
            raise ValueError('Url must not be empty.')
        options = Options()
        options.add_argument('--headless')
        options.add_argument('--no-sandbox')

        driver = webdriver.Chrome(chrome_options=options)
        driver.get(self.url)
        driver.implicitly_wait(10)
        content = driver.page_source
        self.driver = driver
        return content

    def parse(self):
        """
        Provides parsing functionality.

        :return: None
        """
        try:
            loading = True
            while loading:
                loading = self.parse_current_page_content()
                if loading:
                    loaded = False
                    while not loaded:
                        loaded = self.load_next_page()
        except ValueError as val_err:
            self.logger.error('Error while parsing RH.')
            self.logger.error(val_err)
        finally:
            self.driver.close()

    def do_click(self):
        """
        Accomplishes clicking on a web page.

        :return: True if successful
        """
        try:
            elm = self.driver.find_element_by_link_text("›")
            elm.click()
            return True
        except WebDriverException:
            return False

    def load_next_page(self):
        """
        Load web page.

        :return: True if successful
        """
        driver = self.driver
        try:
            click = False
            start = time.time()
            end = time.time()
            while not click:
                if (end - start) > 120:
                    raise ValueError('RedHat page could not be loaded.')
                driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                click = self.do_click()
                self.logger.debug("CLICK in RedHat")
                end = time.time()

            time.sleep(3)
            content = driver.page_source
            self.data = lxml.etree.HTML(content.replace('<br>', ''))
            self.driver = driver
            return True
        except (NoSuchElementException, WebDriverException):
            return False

    def parse_current_page_content(self):
        """
        Parses current page in property data.

        :return: True if next page is needed to load, False otherwise.
        """
        table_rows = self.data.xpath(
            './/table[contains(@summary, "Common Vulnerabilities and Exposures")]//tbody/tr')
        for row in table_rows:
            url_list = row.xpath('.//th//a/@href')
            date_str_list = row.xpath('.//td//time/text()')
            if len(url_list) != 1 or len(date_str_list) != 1:
                raise ValueError('Format of data provided in RH table has changed.')

            date = string_to_date(date_str_list[0], self.date_format)
            if date < self.from_date:
                return False
            if self.from_date <= date <= self.to_date:
                self.entities.append(url_list[0])
                self.entry_added = True
                self.last_added = True
            else:
                self.last_added = False
            if not self.last_added and self.entry_added:
                return False
        return self.last_added or not self.entry_added
