import webkitpy.thirdparty.autoinstalled.selenium
from pltresults import PLTResults
from selenium import webdriver
from time import sleep
from webkitpy.benchmark_runner.utils import get_driver_binary_path
from webkitpy.common.timeout_context import Timeout

# FIXME: we want to avoid hardcoding the offsets
# we use this to make sure the window.innerHeight of each browser is the same
browser_height_offsets = {
    'safari': 76,
    'chrome': 0,
    'firefox': 37,
    'stp': 76,
}


class PageLoadTest(object):

    def __init__(self, iterations, instances, wait, browser, suites, size):
        print("Creating PLT with parameters:")
        print("iterations: {}".format(iterations))
        print("instances: {}".format(instances))
        print("wait: {}s".format(wait))
        print("browser: {}".format(browser))
        print("suites: {}".format([s.name for s in suites]))
        width, height = size
        if width:
            print("width: {}".format(width))
        if height:
            print("height: {}".format(height))
        print("")
        self.iterations = iterations
        self.instances = instances
        self.wait = wait
        self.browser = browser
        self.suites = suites
        self.size = size

    def start(self):
        total_results = PLTResults()
        suiteid = 0
        for suite in self.suites:
            suite.attempts -= 1
            suiteid += 1
            print("------------------------------")
            print("Running suite {id} of {num}: {name}".format(id=suiteid, num=len(self.suites), name=suite.name))
            print("------------------------------")
            print("")
            total_results += self.run_suite(suite)
        total_results.print_results()

    def run_suite(self, suite):
        cold_run_results = PLTResults()
        suite_results = PLTResults()

        for instance in range(self.instances):
            driver = self._get_driver_for_browser(self.browser)
            self._setup_browser_window(driver)
            sleep(5)
            for iteration in range(self.iterations + 1):
                print("------------------------------")
                if iteration == 0:
                    print("Running iternation %s (cold run)" % iteration)
                else:
                    print("Running iternation %s" % iteration)
                run_results = self.run_one_test(suite, driver)
                if not run_results:
                    if suite.attempts <= 0:
                        print("Failed to finish suite {name} after {x} attempts. Results are incomplete.".format(name=suite.name, x=suite.max_attempts))
                        print("Exiting...")
                        quit()
                    else:
                        print("A page failed to load. Re-queuing suite.")
                        self.suites.append(suite)
                        driver.quit()
                        return PLTResults()
                run_results.print_url_results("INDIVIDUAL")
                if iteration == 0:
                    cold_run_results += run_results
                else:
                    suite_results += run_results
            driver.quit()
        cold_run_results.print_results(suite.name, True)
        suite_results.print_results(suite.name)
        return suite_results

    def _get_driver_for_browser(self, browser):
        driver_executable = get_driver_binary_path(browser)
        if browser == 'safari':
            return webdriver.Safari()
        if browser == 'chrome':
            from selenium.webdriver.chrome.options import Options
            options = Options()
            options.add_argument("--disable-web-security")
            options.add_argument("--disable-extensions")
            options.add_argument("--start-maximized")
            return webdriver.Chrome(chrome_options=options, executable_path=driver_executable)
        if browser == 'firefox':
            return webdriver.Firefox(executable_path=driver_executable)
        if browser == 'stp':
            return webdriver.Safari(executable_path='/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver')

    def _setup_browser_window(self, driver):
        driver.maximize_window()
        sleep(1)
        current_size = driver.get_window_size()

        new_width, new_height = self.size
        if not new_width:
            new_width = driver.execute_script('return screen.width;')
            print("setting width to {}".format(new_width))
        if not new_height:
            new_height = current_size['height'] - browser_height_offsets[self.browser]
            print("setting height to {}".format(new_height))

        try:
            driver.set_window_size(width=new_width, height=new_height)
            driver.set_window_position(x=0, y=0)
        except:
            pass

    def run_one_test(self, suite, driver):
        tabs = False
        currentTabIdx = 0
        maxTabs = 5
        maxRetrys = 5
        timeout = 30

        local_results = PLTResults()

        for url in suite.urls:
            if tabs:
                if currentTabIdx < maxTabs - 1:
                    raise NotImplementedError("Opening new tabs is not supported yet.")
                driver.switch_to_window(driver.window_handles[currentTabIdx % maxTabs])
                currentTabIdx += 1
            tempWait = self.wait
            for attempt in range(maxRetrys):
                driver.set_page_load_timeout(timeout)
                try:
                    driver.get(url)
                except:
                    print("{url} timed out after {time} seconds.".format(url=url, time=timeout))
                    return None

                sleep(tempWait)
                if self.get_results(driver, local_results, url):
                    break

                print("Could not get results for {url}. Retrying...".format(url=url))
                tempWait += 0.5
                if attempt == maxRetrys - 1:
                    return None
        return local_results

    def get_results(self, driver, results, url):
        nt_results = driver.execute_script('return performance.getEntriesByType("navigation")[0]')  # navigation timing 2
        if not nt_results:
            nt_results = driver.execute_script('return performance.timing')  # navigation timing 1
            start = nt_results['navigationStart']
            end = nt_results['loadEventEnd']
            if start == 0 or end == 0:
                return False
        else:
            start = nt_results['startTime']
            end = nt_results['loadEventEnd']
            if end == 0:
                return False

        results.add_timing_result(end - start, url)
        return True
