import json
import os
from pathlib import Path
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains


from core.models import UserAccount
from functional_tests.util import GradyTestCase, login, reset_browser_after_test
from util import factory_boys as fact


def expect_file_to_be_downloaded(path):
    """
    Checks if a file has finished downloading by checking if a file exists at the path and
    no `.part` file is present in the directory containing path
    :param path: path to check
    :return:
    """
    def condition(*args):
        file_present = Path(path).is_file()
        partial_file_present = any(dir_path.suffix == ".part" for
                                   dir_path in Path(path).parent.iterdir())
        return file_present and not partial_file_present
    return condition


JSON_EXPORT_FILE = os.path.join(os.path.dirname(__file__), 'export.json')


class ExportTestModal(GradyTestCase):
    username = None
    password = None
    role = None

    def setUp(self):
        self.username = 'reviewer'
        self.password = 'p'
        self.role = UserAccount.REVIEWER
        fact.UserAccountFactory(
            username=self.username,
            password=self.password,
            role=self.role
        )

    def tearDown(self):
        self.saveScreenshots()
        reset_browser_after_test(self.browser, self.live_server_url)

    def _login(self):
        login(self.browser, self.live_server_url, self.username, self.password)

    def test_export_red_uncorrected_submissions(self):
        def export_btn_is_not_green(*args):
            exports_btn = self.browser.find_element_by_id('export-btn')
            return 'success' not in exports_btn.get_attribute('class')

        fact.SubmissionFactory()
        self._login()
        WebDriverWait(self.browser, 10).until(export_btn_is_not_green)

    def test_export_warning_tooltip_uncorrected_submissions(self):
        fact.SubmissionFactory()
        self._login()
        self.browser.execute_script(
            "document.getElementById('export-btn').dispatchEvent(new Event('mouseenter'));"
        )
        tooltip_uncorrected = self.browser.find_element_by_id('uncorrected-tooltip')
        self.assertNotEqual(None, tooltip_uncorrected)
        self.assertRaises(Exception, self.browser.find_element_by_id, 'corrected-tooltip')

    def test_export_green_all_corrected(self):
        def export_btn_is_green(*args):
            exports_btn = self.browser.find_element_by_id('export-btn')
            return 'success' in exports_btn.get_attribute('class')

        fact.SubmissionTypeFactory()
        self._login()
        WebDriverWait(self.browser, 10).until(export_btn_is_green)

    def test_export_all_good_tooltip_all_corrected(self):
        fact.SubmissionTypeFactory()
        self._login()
        self.browser.execute_script(
            "document.getElementById('export-btn').dispatchEvent(new Event('mouseenter'));"
        )
        tooltip_corrected = self.browser.find_element_by_id('corrected-tooltip')
        self.assertNotEqual(None, tooltip_corrected)
        self.assertRaises(Exception, self.browser.find_element_by_id, 'uncorrected-tooltip')

    def test_export_list_popup_contains_correct_items(self):
        self._login()
        export_btn = self.browser.find_element_by_id('export-btn')
        export_btn.click()
        export_menu = self.browser.find_element_by_class_name('menuable__content__active')
        export_list = export_menu.find_element_by_class_name('v-list')
        list_elements = export_list.find_elements_by_tag_name('div')
        self.assertEqual(2, len(list_elements))
        self.assertEqual('Export student scores', list_elements[0].text)
        self.assertEqual('Export whole instance data', list_elements[1].text)

    def test_export_student_scores_as_json(self):
        fact.StudentInfoFactory()
        fact.SubmissionFactory()
        self._login()
        export_btn = self.browser.find_element_by_id('export-btn')
        export_btn.click()
        export_scores = self.browser.find_element_by_id('export-list0')
        export_scores.click()
        data_export_modal = self.browser.find_element_by_id('data-export-modal')
        data_export_btn = data_export_modal.find_element_by_id('export-data-download-btn')
        ActionChains(self.browser).move_to_element(data_export_btn).click().perform()
        WebDriverWait(self.browser, 10).until(expect_file_to_be_downloaded(JSON_EXPORT_FILE))
        try:
            with open(JSON_EXPORT_FILE) as f:
                data = json.load(f)

            self.assertEqual('B.Inf.4242 Test Module',
                             data[0]['Exams'][0]['exam']['moduleReference'])
        except Exception as e:
            print(data)
            raise e
        finally:
            os.remove(JSON_EXPORT_FILE)

    def test_export_instance(self):
        fact.SubmissionFactory()
        self._login()
        self.browser.find_element_by_id('export-btn').click()
        self.browser.find_element_by_id('export-list1').click()
        instance_export_modal = self.browser.find_element_by_id('instance-export-modal')
        # instance_export_modal.find_element_by_id('instance-export-dl').click()
        export_btn = instance_export_modal.find_element_by_id('instance-export-dl')
        ActionChains(self.browser).move_to_element(export_btn).click().perform()
        WebDriverWait(self.browser, 10).until(expect_file_to_be_downloaded(JSON_EXPORT_FILE))
        try:
            with open(JSON_EXPORT_FILE) as f:
                data = json.load(f)
            self.assertEqual('B.Inf.4242 Test Module', data['examTypes'][0]['moduleReference'])
        except Exception as e:
            raise e
        finally:
            os.remove(JSON_EXPORT_FILE)