# Custom
from model import *
from appstate import * 

# External
from imgui_bundle import (
    imgui,
    imgui_ctx,
    immapp,
    imgui_md,
    im_file_dialog,
    hello_imgui
)

# Built In 
from typing import List
import shelve
from pathlib import Path
from datetime import datetime

def file_info(path: Path) -> None:
    stat = path.stat()
    modified = datetime.fromtimestamp(stat.st_atime)
    created = datetime.fromtimestamp(stat.st_ctime)
    format = '%c'

    data = {
        "File": path.name,
        "Size": f"{stat.st_size/100} KB",
        "Modified": modified.strftime(format),
        "Created": created.strftime(format)
    }
    
    if imgui.begin_table("File Info", 2):
        imgui.table_setup_column(" ", 0)
        imgui.table_setup_column(" ")
        
        for k, v in data.items():
            imgui.push_id(k)
            imgui.table_next_row()
            imgui.table_next_column()
            imgui.text(k)
            imgui.table_next_column()
            imgui.text(v)
            imgui.pop_id()
        imgui.end_table()

@immapp.static(inited=False, res=False)
def select_file(app_state: AppState):
    statics = select_file
    if not statics.inited:
        statics.res = None
        statics.current = None
        with shelve.open("state") as state:
            statics.current = Path(state["DB"])
        statics.inited = True
    
    imgui_md.render("# Database Manager")
    file_info(statics.current)
   
    if imgui.button("Open File"):
        im_file_dialog.FileDialog.instance().open("SelectDatabase", "Open Database", "Database File (*.json;*.db){.json,.db}")
    if im_file_dialog.FileDialog.instance().is_done("SelectDatabase"):
        if im_file_dialog.FileDialog.instance().has_result():
            statics.res = im_file_dialog.FileDialog.instance().get_result()
            LOG_INFO(f"Load File {statics.res}")
        im_file_dialog.FileDialog.instance().close()

    if statics.res:
        filename = statics.res.filename()
        info = Path(statics.res.path())
       
        imgui.separator()
        file_info(info)       

        file = None
        if imgui.button("Load"):
            if not db.is_closed():
                db.close()

            if statics.res.extension() == '.json':
                file = filename.removesuffix('.json')
                file = file + '.db'
                db.init(file)
                db.connect(reuse_if_open=True)
                db.create_tables([Class, Student, Lecture, Submission])
                load_from_json(str(info))
                LOG_INFO(f"Successfully created {file}")
            
            if statics.res.extension() == '.db':
                file = str(statics.res.path())
                db.init(file)
                db.connect(reuse_if_open=True)
                db.create_tables([Class, Student, Lecture, Submission])
                LOG_INFO(f"Successfully loaded {filename}")

            with shelve.open("state") as state:
                state["DB"] = file
            app_state.update()
            statics.res = None

@immapp.static(inited=False)
def table(app_state: AppState) -> None:
    statics = table
    if not statics.inited:
        statics.class_id = None
        statics.lectures = None
        statics.points = list()
        statics.inited = True
    
    if statics.class_id != app_state.current_class_id:
        statics.class_id = app_state.current_class_id
        statics.lectures = Lecture.select().where(Lecture.class_id == statics.class_id)
        statics.data = dict()
        for student in Student.select().where(Student.class_id == statics.class_id):
            subs = Submission.select().where(Submission.student_id == student.id)
            points = [sub.points for sub in subs]
            statics.data[f"{student.prename} {student.surname}"] = points

    if not statics.lectures:
        imgui.text("No Lecture queried")
        return
    
    table_flags = (
        imgui.TableFlags_.row_bg.value
        | imgui.TableFlags_.borders.value 
        | imgui.TableFlags_.resizable.value 
        | imgui.TableFlags_.sizing_stretch_same.value
    )

    if imgui.begin_table("Overview", len(statics.lectures)+1, table_flags):
        imgui.table_setup_column("Students")
        for n, lecture in enumerate(statics.lectures, start=1):
            imgui.table_setup_column(f"{n}. {lecture.title} ({lecture.points})") 
        imgui.table_setup_scroll_freeze(1, 1)
        imgui.table_headers_row()

        for k, v in statics.data.items():
            imgui.push_id(k)
            imgui.table_next_row()
            imgui.table_next_column()
            imgui.text(k)
            for points in v:
                imgui.table_next_column()
                if points.is_integer():
                    points = int(points)
                imgui.text(str(points))
            imgui.pop_id()

        imgui.end_table()

@immapp.static(inited=False)
def class_editor() -> None:
    statics = class_editor
    if not statics.inited:
        statics.classes = None
        statics.selected = 0
        statics.inited = True

    statics.classes = Class.select()

    imgui_md.render("# Edit Classes")
    _, statics.selected = imgui.combo("Classes", statics.selected, [c.name for c in statics.classes])
    imgui.text(statics.classes[statics.selected].name)

def database_editor(app_state: AppState) -> None:
    class_editor()

def database_docking_splits() -> List[hello_imgui.DockingSplit]: 
    split_main_command = hello_imgui.DockingSplit()
    split_main_command.initial_dock = "MainDockSpace"
    split_main_command.new_dock = "CommandSpace"
    split_main_command.direction = imgui.Dir.down
    split_main_command.ratio = 0.3

    # Log Space
    split_main_command2 = hello_imgui.DockingSplit()
    split_main_command2.initial_dock = "CommandSpace"
    split_main_command2.new_dock = "CommandSpace2"
    split_main_command2.direction = imgui.Dir.right
    split_main_command2.ratio = 0.3

    split_main_misc = hello_imgui.DockingSplit()
    split_main_misc.initial_dock = "MainDockSpace"
    split_main_misc.new_dock = "MiscSpace"
    split_main_misc.direction = imgui.Dir.left
    split_main_misc.ratio = 0.2

    splits = [split_main_misc, split_main_command, split_main_command2]
    return splits

def set_database_editor_layout(app_state: AppState) -> List[hello_imgui.DockableWindow]:
    
    file_dialog = hello_imgui.DockableWindow()
    file_dialog.label = "Database"
    file_dialog.dock_space_name = "MiscSpace"
    file_dialog.gui_function = lambda: select_file(app_state)

    log = hello_imgui.DockableWindow()
    log.label = "Logs"
    log.dock_space_name = "CommandSpace2"
    log.gui_function = hello_imgui.log_gui

    table_view = hello_imgui.DockableWindow()
    table_view.label = "Table"
    table_view.dock_space_name = "MainDockSpace"
    table_view.gui_function = lambda: table(app_state)

    editor = hello_imgui.DockableWindow()
    editor.label = "Editor"
    editor.dock_space_name = "CommandSpace"
    editor.gui_function = lambda: database_editor(app_state)
    
    return [
        file_dialog, log, table_view, editor
    ]

def database_editor_layout(app_state: AppState) -> hello_imgui.DockingParams:
    docking_params = hello_imgui.DockingParams()
    docking_params.layout_name = "Database Editor"
    docking_params.docking_splits = database_docking_splits() 
    docking_params.dockable_windows = set_database_editor_layout(app_state)
    return docking_params
