# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-

#
# Ubuntu Core Webapps
# Copyright (C) 2015 Canonical
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import contextlib
import logging

import autopilot.logging
import ubuntuuitoolkit
from autopilot import platform

logger = logging.getLogger(__name__)


class PageObject():

    """Base page object."""

    def __init__(self, proxy, driver):
        """Initialize the page object.

        :param proxy: The autopilot application proxy.
        :param driver: The webdriver used to introspect and control the web
            container.

        """
        super().__init__()
        self.proxy = proxy
        self.driver = driver

    def get_container_proxy(self):
        return self.proxy.select_single('WebappContainerWebview')

    def find_element_by_css_in_desktop_or_mobile(
            self, desktop_css_selector, mobile_css_selector):
        return self.driver.find_element_by_css_selector(
            '{}, {}'.format(desktop_css_selector, mobile_css_selector))

    @contextlib.contextmanager
    def focused_type(self, input_web_element):
        """Type into an input web element.

        This context manager takes care of making sure a particular
        *input_target* UI control is selected before any text is entered.

        """

        pointer = ubuntuuitoolkit.get_pointing_device()
        pointer.move(*self.get_center_point(input_web_element))
        pointer.click()

        yield ubuntuuitoolkit.get_keyboard()

    def get_center_point(self, web_element):
        web_element_center_x = web_element.location.get('x') + (
            web_element.size.get('width') // 2)
        web_element_center_y = web_element.location.get('y') + (
            web_element.size.get('height') // 2)

        container_x, container_y, _, _ = self.get_container_proxy().globalRect

        return (
            container_x + web_element_center_x,
            container_y + web_element_center_y
        )


class AmazonMainPage(PageObject):

    """Page object for the main page of the Amazon website."""

    @autopilot.logging.log_action(logger.info)
    def search(self, query):
        search_bar = self._get_search_bar()
        self._enter_search_query(search_bar, query)
        go_button = self._get_go_button(search_bar)
        go_button.click()
        return AmazonResultsPage(self.proxy, self.driver)

    def _get_search_bar(self):
        desktop_css_selector = '#nav-searchbar'
        mobile_css_selector = '.nav-searchbar'
        return self.find_element_by_css_in_desktop_or_mobile(
            desktop_css_selector, mobile_css_selector)

    def _enter_search_query(self, search_bar, query):
        desktop_css_selector = '#twotabsearchtextbox'
        mobile_css_selector = 'input.nav-input[type="text"]'
        search_text_field = self.find_element_by_css_in_desktop_or_mobile(
            desktop_css_selector, mobile_css_selector)
        if platform.model() == 'Desktop':
            with self.focused_type(search_text_field) as keyboard:
                keyboard.type(query)
        else:
            # The location returned by the driver in the phone is not accurate.
            # TODO report a bug.
            # XXX We can't send keys because of bug http://pad.lv/1421423
            # Remove the workaround once that bug is fixed.
            # --elopio - 2015-02-12
            # search_text_field.send_keys('Test')
            self.driver.execute_script(
                "document.getElementsByClassName("
                "'nav-searchbar')[0].getElementsByTagName("
                "'input')[1].setAttribute('value', '{}')".format(query)
            )

    def _get_go_button(self, search_bar):
        desktop_css_selector = '.nav-submit-input'
        mobile_css_selector = '.nav-input'
        return self.find_element_by_css_in_desktop_or_mobile(
            desktop_css_selector, mobile_css_selector)


class AmazonResultsPage(PageObject):

    """Page object for the main page of the Amazon Website."""

    def get_search_results_count_label(self):
        desktop_css_selector = '#s-result-count'
        mobile_css_selector = '#results span'
        return self.find_element_by_css_in_desktop_or_mobile(
            desktop_css_selector, mobile_css_selector).text
