# -*- coding: utf-8 -*-
#
# Copyright 2012 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, 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/>.
#
# In addition, as a special exception, the copyright holders give
# permission to link the code of portions of this program with the
# OpenSSL library under certain conditions as described in each
# individual source file, and distribute linked combinations
# including the two.
# You must obey the GNU General Public License in all respects
# for all of the code used other than OpenSSL.  If you modify
# file(s) with this exception, you may extend this exception to your
# version of the file(s), but you are not obligated to do so.  If you
# do not wish to do so, delete this exception statement from your
# version.  If you delete this exception statement from all source
# files in the program, then also delete it here.
"""Test Ubunto SSO Wizard."""

from PyQt4 import QtGui
from twisted.internet import defer

from ubuntu_kylin_sso.tests import (
    APP_NAME,
    EMAIL,
    PASSWORD,
)
from ubuntu_kylin_sso.qt import PREFERED_UI_SIZE, ubuntu_sso_wizard
from ubuntu_kylin_sso.qt.tests import (
    BaseTestCase,
    FakeOverlay,
)
from ubuntu_kylin_sso.utils import compat


# is ok to access private method/attrs in tests
# pylint: disable=W0212


class UbuntuSSOClientGUITestCase(BaseTestCase):

    """Test the UbuntuSSOClientGUI class."""

    ui_class = ubuntu_sso_wizard.UbuntuSSOClientGUI
    ui_wizard_class = None

    @defer.inlineCallbacks
    def setUp(self):
        self.patch(ubuntu_sso_wizard.networkstate, 'is_machine_connected',
            lambda: True)
        yield super(UbuntuSSOClientGUITestCase, self).setUp()
        self.patch(ubuntu_sso_wizard.sys, 'exit', self._set_called)

    def test_closing_main_window(self):
        """When closing the main window, USER_CANCELLATION is returned."""
        self.ui.close()
        self.assertEqual(self._called,
            ((ubuntu_sso_wizard.USER_CANCELLATION,), {}))

    def test_close_main_window_reaching_success_page(self):
        """Closing the window in success page, USER_SUCCESS is returned."""
        self.ui.wizard._move_to_success_page()
        self.ui.close()
        self.assertEqual(self._called,
            ((ubuntu_sso_wizard.USER_SUCCESS,), {}))

    def test_closing_wizard_no_parent(self):
        """When closing the wizard, USER_CANCELLATION is returned."""
        self.ui.wizard.setParent(None)
        self.ui.wizard.close()
        self.assertEqual(self._called,
            ((ubuntu_sso_wizard.USER_CANCELLATION,), {}))

    def test_close_wizard_no_parent_reaching_success_page(self):
        """Closing the wizard in success page, USER_SUCCESS is returned."""
        self.ui.wizard.setParent(None)
        self.ui.wizard._move_to_success_page()
        self.ui.wizard.close()
        self.assertEqual(self._called,
            ((ubuntu_sso_wizard.USER_SUCCESS,), {}))

    def test_on_wizard_finish_done_called(self):
        """Test that the wizard actually close the window on finish."""
        self.ui.wizard._move_to_success_page()
        finish_button = self.ui.wizard.button(QtGui.QWizard.FinishButton)
        self.patch(self.ui.wizard, 'done', self._set_called)
        finish_button.clicked.emit(True)
        self.assertEqual(self._called, ((1,), {}))

    def test_on_wizard_finish_close_called_on_done(self):
        """Test that the wizard actually close the window on finish."""
        self.ui.wizard._move_to_success_page()
        finish_button = self.ui.wizard.button(QtGui.QWizard.FinishButton)
        self.patch(self.ui.wizard, 'closeEvent', self._set_called)
        finish_button.clicked.emit(True)
        self.assertEqual(self._called, ((None,), {}))

    def test_window_title(self):
        """Check the window title for the application."""
        title = compat.text_type(self.ui.windowTitle())
        self.assertEqual(title, ubuntu_sso_wizard.WINDOW_TITLE)


class UbuntuSSOWizardTestCase(BaseTestCase):

    """Test case for UbuntuSSOWizard class."""

    ui_class = ubuntu_sso_wizard.UbuntuSSOWizard
    ui_signals = ('recoverableError', 'loginSuccess', 'registrationSuccess')
    ui_wizard_class = None

    @defer.inlineCallbacks
    def setUp(self):
        self.patch(ubuntu_sso_wizard.networkstate, 'is_machine_connected',
            lambda: True)
        self.patch(ubuntu_sso_wizard, 'LoadingOverlay', FakeOverlay)
        yield super(UbuntuSSOWizardTestCase, self).setUp()

    def test_window_size(self):
        """check the window size."""
        size = self.ui.size()
        self.assertTrue(size.height() >= PREFERED_UI_SIZE['height'])
        self.assertTrue(size.width() >= PREFERED_UI_SIZE['width'])

    def test_move_to_success_page_state(self):
        """Test _move_to_success_page method."""
        self.patch(self.ui, 'setButtonLayout', self._set_called)
        self.ui._move_to_success_page()
        self.assertEqual(self.ui._next_id, -1)
        self.assertEqual(self.ui._next_id, -1)
        self.assertEqual(self._called,
            (([QtGui.QWizard.Stretch, QtGui.QWizard.FinishButton],), {}))
        self.assertTrue(self.ui.button(QtGui.QWizard.FinishButton).isEnabled())
        self.assertEqual(self.ui.exit_code, ubuntu_sso_wizard.USER_SUCCESS)

    def test_overlay_shows(self):
        """Test if the signals call the overlay.show properly."""
        # reset the counter
        self.ui.overlay.show_counter = 0

        for page in self.ui._pages:
            page.show_overlay()

        self.assertEqual(self.ui.overlay.show_counter, len(self.ui._pages))

    def test_overlay_hides(self):
        """Test if the signals call the overlay.show properly."""
        # reset the counter
        self.ui.overlay.show_counter = 0

        for page in self.ui._pages:
            page.hide_overlay()

        # We do +1 because a hide action is executed on the wizard init.
        self.assertEqual(self.ui.overlay.hide_counter,
            len(self.ui._pages) + 1)

    def test_go_back_to_current_user_sign_in(self):
        """Move the wizard back to the current user sign in page."""
        self.patch(self.ui, '_go_back_to_page', self._set_called)
        self.ui._next_id = self.ui.current_user_page_id
        self.ui.next()
        self.ui._move_to_reset_password_page()
        self.ui.reset_password.passwordChanged.emit('')
        expected = ((self.ui.current_user,), {})
        self.assertEqual(expected, self._called)

    def test_email_verification_page_params_from_current_user(self):
        """Tests that email_verification_page receives the proper params."""
        self.ui._next_id = self.ui.current_user_page_id
        self.ui.next()
        self.ui.current_user.ui.email_edit.setText(EMAIL)
        self.ui.current_user.ui.password_edit.setText(PASSWORD)
        self.ui.current_user.on_user_not_validated(APP_NAME, EMAIL)
        self.assertEqual(EMAIL, self.ui.email_verification.email)
        self.assertEqual(PASSWORD, self.ui.email_verification.password)

    def test_email_verification_page_params_from_setup(self):
        """Tests that email_verification_page receives the proper params."""
        self.ui._next_id = self.ui.setup_account_page_id
        self.ui.next()
        self.ui.setup_account.ui.email_edit.setText(EMAIL)
        self.ui.setup_account.ui.password_edit.setText(PASSWORD)
        self.ui.setup_account.on_user_registered(APP_NAME, {})
        self.assertEqual(EMAIL, self.ui.email_verification.email)
        self.assertEqual(PASSWORD, self.ui.email_verification.password)

    def test_check_network_connection(self):
        """Test that _connection_detected is executed with connection."""
        self.patch(self.ui, "_connection_detected", self._set_called)
        self.ui.check_network_connection()
        self.assertEqual(self._called, ((), {}))

    def test_check_network_connection_without_connection(self):
        """Test that _connection_detected is executed without connection."""
        self.patch(self.ui, "_connection_detected", self._set_called)
        self.patch(ubuntu_sso_wizard.networkstate, 'is_machine_connected',
            lambda: False)
        self.ui.check_network_connection()
        self.assertFalse(self._called)
