# library για σύνδεση και κατέβασμα αρχείων από το myschool
# στόχος είναι το κάθε script να μπορεί να κάνει πχ:
# driver = get_driver(headless=True)
# download_report(driver, "Γενική τμημάτων","με μητέρα","target_file.xls")

import pathlib, time, os, configparser
from contextlib import contextmanager

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import (
    TimeoutException,
    NoSuchElementException,
    StaleElementReferenceException
)
from selenium.webdriver.firefox.service import Service as FirefoxService

from gr_sch_helper import sch as schHelper

# Τα id του mySchool για την κάθε τάξη
grade_links = {
    "ΑΛ":"ctl00_ContentData_lstLevel_6043_D",
    "ΒΛ":"ctl00_ContentData_lstLevel_6044_D",
    "ΓΛ":"ctl00_ContentData_lstLevel_6045_D",
}

report_shortcodes = schHelper.report_shortcodes

report_types = {
    "csv":"ReportToolbar1_Menu_ITCNT13_SaveFormat_DDD_L_LBI7T0",
}

class MySchool:
    def __init__(self, config_file, dl_path, headless):
        self.dl_path = dl_path
        config = configparser.ConfigParser()
        config.read(config_file, 'UTF-8')
        firefox_options = Options()
        firefox_options.add_argument("--window-size=1440,900")
        firefox_options.add_argument("--disable-gpu")
        firefox_options.add_argument("--disable-extensions")
        firefox_options.set_preference("browser.download.folderList", 2)
        firefox_options.set_preference("browser.download.dir", str(dl_path))
        if headless: firefox_options.add_argument("--headless")

        self.driver = webdriver.Firefox(
            options=firefox_options,
        )
        self.wait =  WebDriverWait(self.driver, timeout=5, poll_frequency=.2)
        self.driver.get("https://myschool.sch.gr/")
        self.driver.find_element(By.LINK_TEXT, "Σύνδεση").click()
        WebDriverWait(self.driver, 30).until(lambda d: bool(d.find_element(By.ID, "username")))
        self.driver.find_element(By.ID, "username").send_keys(config["Myschool"]["Username"])
        WebDriverWait(self.driver, 30).until(lambda d: bool(d.find_element(By.ID, "password")))
        self.driver.find_element(By.ID, "password").send_keys(config["Myschool"]["Password"])
        WebDriverWait(self.driver, 30).until(lambda d: bool(d.find_element(By.ID, "loginButton")))
        self.driver.find_element(By.ID, "loginButton").click()
        self.report_name = None

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        self.driver.quit()

    def wait_get_one(self, by_type, by_string):
        try:
            return self.wait.until(lambda d: d.find_element(by_type, by_string))
        except (TimeoutException, NoSuchElementException, StaleElementReferenceException):
            return False

    def wait_get_many(self, by_type, by_string):
        self.wait.until(lambda d: bool(d.find_elements(by_type, by_string)))
        return self.driver.find_elements(by_type, by_string)
    
    def goto(self,report_name):
        self.report_name = report_name
        self.driver.get(report_shortcodes[report_name].url)

    def provoli(self,provoli):
        self.driver.find_element(By.ID,"ctl00_ContentData_cmbViews_I").click()
        elements = self.driver.find_elements(By.CLASS_NAME, "dxeListBoxItem")
        target = next((el for el in elements if el.text.strip() == provoli), None)
        target.click()

    def select_grades(self,grades):
        for grade in grades:
            self.driver.find_element(By.ID,grade_links[grade]).click()
            WebDriverWait(self.driver, 60).until(EC.element_to_be_clickable((By.ID, "ctl00_ContentData_cbpStudents_lstStudents_LBI1C")))

    def open_extra_criteria(self):
        self.driver.find_element(By.ID,"ctl00_ContentData_btnCriteriaPlus").click()
        iframe = WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))
        self.driver.switch_to.frame(iframe)

    def close_extra_criteria(self):
        self.driver.find_element(By.XPATH,"//a[normalize-space()='Αποδοχή']").click()
        self.driver.switch_to.default_content()

    def click_until(self, elem_id, target_class, max_tries):
        wait = WebDriverWait(self.driver, 30)
        tries = 0
        while tries < max_tries:
            elem = wait.until(EC.element_to_be_clickable((By.ID, elem_id)))
            classes = elem.get_attribute("class").split()
            if target_class in classes:
                break
            elem.click()
            tries += 1
            time.sleep(0.2)

    def get_type(self,report_type):
        self.driver.find_element(By.ID, "ctl00_ContentData_navig_preview").click()
        filename = report_shortcodes[self.report_name].basename + "." + report_type
        downloadedFile = pathlib.Path(self.dl_path / filename)
        time.sleep(15)
        WebDriverWait(self.driver, 60).until(
            EC.visibility_of_element_located((By.ID, "ReportViewer1_ContentFrame"))
        )
        self.driver.execute_script(f"""
var cb = aspxGetControlCollection().Get('ReportToolbar1_Menu_ITCNT13_SaveFormat');
cb.SetValue('{report_type}');
""")
        self.driver.find_element(By.ID, "ReportToolbar1_Menu_DXI11_").click()
        WebDriverWait(self.driver, 60).until(lambda d: os.path.exists(downloadedFile))
        return downloadedFile

    def get_plain(self):
        filename = report_shortcodes[self.report_name].basename + ".xls"
        downloadedFile = pathlib.Path(self.dl_path / filename)
        # if file exists mv to filename.back.n
        self.driver.find_element(By.ID, "ctl00_ContentData_navig_preview").click()
        WebDriverWait(self.driver, 60).until(lambda d: os.path.exists(downloadedFile))
        return downloadedFile
            
def get_webdriver(config_file, dl_path, headless):
    return MySchool(config_file, dl_path, headless)
                   
    
