# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from marionette import Wait
from marionette.by import By
from gaiatest.apps.base import Base
from gaiatest.apps.base import PageRegion
from gaiatest.apps.email.regions.setup import SetupEmail
from gaiatest.apps.email.regions.setup import ManualSetupEmail
from gaiatest.apps.email.regions.settings import Settings


class Email(Base):

    name = 'E-Mail'

    _email_locator = (By.CSS_SELECTOR, '#cardContainer .msg-header-item:not([data-index="-1"])')
    _syncing_locator = (By.CSS_SELECTOR, '#cardContainer .msg-messages-syncing > .small')
    _manual_setup_locator = (By.CSS_SELECTOR, '#cardContainer .sup-manual-config-btn')
    _message_list_locator = (By.CSS_SELECTOR, '.card-message-list')
    _refresh_button_locator = (By.CLASS_NAME, 'msg-refresh-btn')

    def basic_setup_email(self, name, email, password):

        setup = SetupEmail(self.marionette)
        setup.type_name(name)
        setup.type_email(email)
        setup.type_password(password)
        setup.tap_next()

        setup.tap_account_prefs_next()

        setup.wait_for_setup_complete()

        setup.tap_continue()
        self.wait_for_message_list()

    def setup_IMAP_email(self, imap):
        basic_setup = SetupEmail(self.marionette)
        basic_setup.type_name(imap['name'])
        basic_setup.type_email(imap['email'])
        basic_setup.type_password(imap['password'])
        setup = self.tap_manual_setup()

        setup.select_account_type('IMAP+SMTP')

        setup.type_imap_hostname(imap['imap_hostname'])
        setup.type_imap_name(imap['imap_name'])
        setup.type_imap_port(imap['imap_port'])

        setup.type_smtp_hostname(imap['smtp_hostname'])
        setup.type_smtp_name(imap['smtp_name'])
        setup.type_smtp_port(imap['smtp_port'])

        setup.tap_next()

        setup.tap_account_prefs_next()

        setup.wait_for_setup_complete()
        setup.tap_continue()
        self.wait_for_message_list()

    def setup_active_sync_email(self, active_sync):
        basic_setup = SetupEmail(self.marionette)
        basic_setup.type_name(active_sync['name'])
        basic_setup.type_email(active_sync['email'])
        basic_setup.type_password(active_sync['password'])
        setup = self.tap_manual_setup()

        setup.select_account_type('ActiveSync')

        setup.type_activesync_hostname(active_sync['active_sync_hostname'])
        setup.type_activesync_name(active_sync['active_sync_username'])

        setup.tap_next()

        setup.check_for_emails_interval('20000')
        setup.tap_account_prefs_next()

        setup.wait_for_setup_complete()
        setup.tap_continue()
        self.wait_for_message_list()

    def delete_email_account(self, index):

        toolbar = self.header.tap_menu()
        toolbar.tap_settings()
        settings = Settings(self.marionette)
        account_settings = settings.email_accounts[index].tap()
        delete_confirmation = account_settings.tap_delete()
        delete_confirmation.tap_delete()

    def tap_manual_setup(self):
        self.wait_for_element_displayed(*self._manual_setup_locator)
        self.marionette.find_element(*self._manual_setup_locator).tap()
        return ManualSetupEmail(self.marionette)

    @property
    def header(self):
        return Header(self.marionette)

    @property
    def toolbar(self):
        return ToolBar(self.marionette)

    @property
    def mails(self):
        return [Message(self.marionette, mail) for mail in self.marionette.find_elements(*self._email_locator)]

    def wait_for_emails_to_sync(self):
        element = self.marionette.find_element(*self._refresh_button_locator)
        self.wait_for_condition(
            lambda m: element.get_attribute(
                'data-state') == 'synchronized')

    def wait_for_message_list(self):
        element = self.marionette.find_element(*self._message_list_locator)
        self.wait_for_condition(
            lambda m: element.is_displayed() and
            element.location['x'] == 0)

    def wait_for_email(self, subject, timeout=120):
        Wait(self.marionette, timeout, interval=5).until(
            self.email_exists(self, subject))

    class email_exists(object):

        def __init__(self, app, subject):
            self.app = app
            self.subject = subject

        def __call__(self, marionette):
            if self.subject in [mail.subject for mail in self.app.mails]:
                return True
            else:
                self.app.toolbar.tap_refresh()
                self.app.wait_for_emails_to_sync()
                self.app.mails[0].scroll_to_message()
                return False


class Header(Base):

    _menu_button_locator = (By.CSS_SELECTOR, '.card.center .msg-folder-list-btn')
    _compose_button_locator = (By.CSS_SELECTOR, '.card.center .msg-compose-btn')
    _label_locator = (By.CSS_SELECTOR, '.card.center .msg-list-header-folder-label.header-label')

    def tap_menu(self):
        self.marionette.find_element(*self._menu_button_locator).tap()
        toolbar = ToolBar(self.marionette)
        self.wait_for_condition(lambda m: toolbar.is_visible)
        return toolbar

    def tap_compose(self):
        self.marionette.find_element(*self._compose_button_locator).tap()
        from gaiatest.apps.email.regions.new_email import NewEmail
        return NewEmail(self.marionette)

    @property
    def label(self):
        return self.marionette.find_element(*self._label_locator).text

    @property
    def is_menu_visible(self):
        return self.is_element_displayed(*self._menu_button_locator)

    @property
    def is_compose_visible(self):
        return self.is_element_displayed(*self._compose_button_locator)


class ToolBar(Base):
    _toolbar_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .fld-nav-toolbar')
    _refresh_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .msg-refresh-btn')
    _search_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .msg-search-btn')
    _edit_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .msg-edit-btn')
    _settings_locator = (By.CSS_SELECTOR, '#cardContainer .card.center .fld-nav-settings-btn')

    def tap_refresh(self):
        self.wait_for_element_displayed(*self._refresh_locator)
        self.marionette.find_element(*self._refresh_locator).tap()

    def tap_search(self):
        self.wait_for_element_displayed(*self._search_locator)
        self.marionette.find_element(*self._search_locator).tap()

    def tap_edit(self):
        self.wait_for_element_displayed(*self._edit_locator)
        self.marionette.find_element(*self._edit_locator).tap()

    def tap_settings(self):
        self.wait_for_element_displayed(*self._settings_locator)
        self.marionette.find_element(*self._settings_locator).tap()

    @property
    def is_visible(self):
        return self.marionette.find_element(*self._toolbar_locator).location['x'] == 0

    @property
    def is_refresh_visible(self):
        return self.is_element_displayed(*self._refresh_locator)

    @property
    def is_search_visible(self):
        return self.is_element_displayed(*self._search_locator)

    @property
    def is_edit_visible(self):
        return self.is_element_displayed(*self._edit_locator)

    @property
    def is_settings_visible(self):
        return self.is_element_displayed(*self._settings_locator)


class Message(PageRegion):
    _subject_locator = (By.CSS_SELECTOR, '.msg-header-subject')
    _senders_email_locator = (By.CSS_SELECTOR, '.msg-header-author')

    @property
    def subject(self):
        return self.root_element.find_element(*self._subject_locator).text

    @property
    def senders_email(self):
        return self.root_element.find_element(*self._senders_email_locator).text

    def scroll_to_message(self):
        self.marionette.execute_script("arguments[0].scrollIntoView(false);", [self.root_element])

    def tap_subject(self):
        el = self.root_element.find_element(*self._subject_locator)
        # TODO: Remove scrollIntoView when bug #877163 is fixed
        self.marionette.execute_script("arguments[0].scrollIntoView(false);", [el])
        self.wait_for_element_displayed(*self._subject_locator)
        self.root_element.find_element(*self._subject_locator).tap()
        from gaiatest.apps.email.regions.read_email import ReadEmail
        return ReadEmail(self.marionette)
