import os
import os.path
from time import sleep
from unittest import skipUnless

from django.contrib.staticfiles.finders import find
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test.utils import override_settings
from selenium import webdriver
from selenium.webdriver.common.by import By

from .utils import get_upload_directory, remove_upload_directory, sha1


CHROMIUM = "chromium"
FIREFOX = "firefox"
SELENIUM = os.environ.get("SELENIUM")


@skipUnless(
    SELENIUM,
    "Set the SELENIUM env variable to 'firefox' or 'chromium' to run selenium tests",
)
class TestAdminPanelWidget(StaticLiveServerTestCase):
    fixtures = ["test_admin.json"]

    @classmethod
    def setUpClass(cls):
        if SELENIUM == CHROMIUM:
            options = webdriver.ChromeOptions()
            options.add_argument("--headless")
            options.add_argument("--disable-gpu")
            cls.selenium = webdriver.Chrome(chrome_options=options)
        elif SELENIUM == FIREFOX:
            cls.selenium = webdriver.Firefox()
        super().setUpClass()

    @classmethod
    def tearDownClass(cls):
        cls.selenium.quit()
        super().tearDownClass()

    def setUp(self):
        remove_upload_directory()

    def test_admin_panel_widget(self):
        self._login_to_admin()
        self._go_to_demo_application_in_admin()
        self._assert_editor_loaded()
        self._focus_cursor_in_editor()
        self._enter_test_text()
        self._open_image_upload_widget()
        self._go_to_upload_tab()
        self._switch_to_form_iframe()
        self._upload_image()
        self._assert_image_uploaded()

    def _login_to_admin(self):
        self.selenium.get("{}{}".format(self.live_server_url, "/admin/"))
        username_input = self.selenium.find_element(By.NAME, "username")
        username_input.send_keys("test")
        password_input = self.selenium.find_element(By.NAME, "password")
        password_input.send_keys("test")
        self.selenium.find_element(By.XPATH, '//input[@value="Log in"]').click()

    def _go_to_demo_application_in_admin(self):
        self.selenium.get(
            "{}{}".format(
                self.live_server_url, "/admin/demo_application/examplemodel/add/"
            )
        )

    def _assert_editor_loaded(self):
        sleep(2)
        self.selenium.find_element(By.ID, "cke_id_content")

    def _focus_cursor_in_editor(self):
        self.frame = self.selenium.find_element(By.CLASS_NAME, "cke_wysiwyg_frame")
        self.frame.click()

    def _enter_test_text(self):
        self.frame.send_keys("test")

    def _open_image_upload_widget(self):
        self.selenium.find_element(
            By.CSS_SELECTOR, "span.cke_button_icon.cke_button__image_icon"
        ).click()
        sleep(1)

    def _go_to_upload_tab(self):
        self.selenium.find_element(By.CSS_SELECTOR, "a[title='Upload']").click()
        sleep(1)

    def _switch_to_form_iframe(self):
        iframe = self.selenium.find_element(
            By.CSS_SELECTOR, "iframe.cke_dialog_ui_input_file"
        )
        self.selenium.switch_to.frame(iframe)

    def _upload_image(self):
        input = self.selenium.find_element(By.CSS_SELECTOR, "input[type=file]")
        input.send_keys(self._get_upload_file())
        self.selenium.switch_to.default_content()
        self.selenium.find_element(By.CLASS_NAME, "cke_dialog_ui_fileButton").click()
        sleep(2)

    def _get_upload_file(self):
        return find("ckeditor/ckeditor/skins/moono/images/hidpi/close.png")

    def _assert_image_uploaded(self):
        upload_directory = get_upload_directory()
        expected_image_path = os.path.join(upload_directory, "close.png")
        expected_thumbnail_path = os.path.join(upload_directory, "close_thumb.png")
        self.assertTrue(os.path.isfile(expected_image_path))
        self.assertTrue(os.path.isfile(expected_thumbnail_path))
        self._assert_uploaded_image_did_not_changed(expected_image_path)
        self._assert_thumbnail_is_not_empty(expected_thumbnail_path)
        os.remove(expected_image_path)
        os.remove(expected_thumbnail_path)

    def _assert_uploaded_image_did_not_changed(self, path):
        expected_sha = sha1(self._get_upload_file())
        uploaded_sha = sha1(path)
        self.assertEqual(expected_sha, uploaded_sha)

    def _assert_thumbnail_is_not_empty(self, path):
        size = os.path.getsize(path)
        assert size > 0


@override_settings(CKEDITOR_IMAGE_BACKEND="ckeditor_uploader.backends.DummyBackend")
class TestAdminPanelWidgetForDummyImageBackend(TestAdminPanelWidget):
    def _assert_image_uploaded(self):
        upload_directory = get_upload_directory()
        expected_image_path = os.path.join(upload_directory, "close.png")
        expected_thumbnail_path = os.path.join(upload_directory, "close_thumb.png")
        self.assertTrue(os.path.isfile(expected_image_path), expected_image_path)
        self.assertFalse(
            os.path.exists(expected_thumbnail_path), expected_thumbnail_path
        )
        self._assert_uploaded_image_did_not_changed(expected_image_path)
        os.remove(expected_image_path)
