from imgui_bundle import (
    imgui,
    immapp,
    imgui_md,
    im_file_dialog,
    immvision,
    ImVec2
)

from peewee import fn
from slugify import slugify
import cairosvg
from PIL import Image
import numpy as np

from pathlib import Path
import subprocess, os, platform
from datetime import datetime
from itertools import compress
import io

from dbmodel import *
from grader import get_grader, get_gradings
from .analyzer_state import AnalyzerState
from .plotter import plot_pdf
from pdf import *

state = AnalyzerState()


@immapp.static(inited=False)
def ranking(class_id: int) -> None:
    if class_id < 1:
        return

    statics = ranking
    
    if not statics.inited:
        statics.class_id = class_id
        statics.data = [
            (f"{student.prename} {student.surname}", Submission.select(fn.SUM(Submission.points)).where(Submission.student_id == student.id).scalar()) 
            for student in Student.select().where(Student.class_id == class_id)
        ]
        statics.data.sort(key = lambda tup: tup[1], reverse=True)
        statics.inited = True

    if statics.class_id != class_id:
        statics.inited = False
    
    imgui_md.render_unindented(f"# Ranking - {Class.get_by_id(statics.class_id).name}")
   
    if len(statics.data) < 1:
        return
    
    if imgui.begin_table("Ranking", 3, imgui.TableFlags_.sizing_fixed_fit.value):
        for n, d in enumerate(statics.data, start=1):
            student, points = d 
            if points.is_integer():
                points = int(points)
            imgui.table_next_row()
            imgui.table_next_column()
            imgui.text(f"{n}.")
            imgui.table_next_column()
            imgui.text(student)
            imgui.table_next_column()
            imgui.text(f"{points} Points")
        imgui.end_table()


@immapp.static(inited=False)
def lecture_list(class_id: int) -> None:
    imgui_md.render_unindented("# Lectures")

    if class_id < 1:
        return

    statics = lecture_list
    if not statics.inited:
        statics.class_id = class_id
        statics.data = [
            (lecture, Submission.select().where(Submission.lecture_id == lecture.id).count())
             for lecture in Lecture.select().where(Lecture.class_id == class_id)
        ]
        statics.inited = True 

    if statics.class_id != class_id:
        statics.inited = False
    

    if imgui.button("Add Lecture"):
        imgui.open_popup("Lecture")
    
    if add_lecture(statics.class_id):
        statics.inited = False
    
    if len(statics.data) < 1:
        return

    if imgui.begin_table("Lectures", 2, imgui.TableFlags_.sizing_fixed_fit.value):
        for n, d in enumerate(statics.data, start=1):
            lecture, sub_count = d 
            imgui.table_next_row()
            imgui.table_next_column()
            
            if imgui.button(f"X##{lecture.title}"):
                lecture.delete_instance()
                statics.inited = False

            imgui.same_line()
            imgui.text(lecture.title)
            imgui.table_next_column()
            imgui.text(f"{lecture.points} Points")
        imgui.end_table()        
    

@immapp.static(inited=False)
def add_lecture(class_id: int) -> bool:
    statics = add_lecture

    if not statics.inited:
        statics.title = str()
        statics.points = float()
        statics.inited = True

    center = imgui.get_main_viewport().get_center()
    imgui.set_next_window_pos(center, imgui.Cond_.appearing.value, ImVec2(0.5, 0.5))

    if imgui.begin_popup("Lecture", imgui.WindowFlags_.always_auto_resize.value):
        imgui_md.render_unindented("# New Lecture")

        _, statics.title = imgui.input_text("Title", statics.title)
        
        _, statics.points = imgui.input_float("Points", statics.points, 0.5, 2.0, "%.1f")

        if statics.points < 0:
            statics.points = float()

        if imgui.button("Add"):
            lecture = Lecture.create(
                title = statics.title,
                points = statics.points,
                class_id = class_id
            )
    
            sub_data = [
                {"student_id": s.id, "lecture_id": lecture.id, "class_id": class_id, "points": 0.0}
                for s in Student.select().where(Student.class_id == class_id)
            ]
            
            Submission.insert_many(sub_data).execute()

            statics.inited = False
            imgui.close_current_popup()
            imgui.end_popup()
            return True

        imgui.same_line()
        
        if imgui.button("Cancel"):
            imgui.close_current_popup()
            statics.inited = False

        imgui.end_popup()

    return False

@immapp.static(inited=False)
def group_list(class_id: int) -> None:
    imgui_md.render_unindented('# Groups')
    if class_id < 1:
        return
    
    statics = group_list
    if not statics.inited:
        statics.class_id = class_id
        statics.groups = list(Group.select().where(Group.class_id == class_id))
        statics.inited = True
    
    if statics.class_id != class_id:
        statics.inited = False
   
    if imgui.button("Add Group"):
        imgui.open_popup("Group")
    
    if add_group(statics.class_id):
        statics.inited = False

    if imgui.begin_table("Groups", 2, imgui.TableFlags_.sizing_fixed_fit.value):
        for n, group in enumerate(statics.groups, start=1):
             
            imgui.table_next_row()
            imgui.table_next_column()
            
            if group.name != 'NoGroup': 
                if imgui.button(f"X##{group.name}"):
                    # Put Students in NoGroup
                    students = Student.select().where(Student.group_id == group.id)
                    nogroup = Group.select().where(Group.class_id == statics.class_id and Group.name == 'NoGroup').get()
                    for student in students:
                        student.group_id = nogroup.id 
                    with db.atomic():
                        Student.bulk_update(students, fields=[Student.group_id], batch_size=50)
                    group.delete_instance()
                    statics.inited = False

                imgui.same_line()
            imgui.text(group.name)
            imgui.table_next_column()
            imgui.text(f"{group.project}")
        imgui.end_table()


@immapp.static(inited=False)
def add_group(class_id: int) -> bool:
    statics = add_group
    if not statics.inited:
        statics.class_id = class_id
        statics.name = str()
        statics.project = str()

        nogroup = None
        for group in Group.select().where(Group.class_id == class_id):
            if group.name == 'NoGroup':
                nogroup = group 
                break

        statics.students = list(Student.select().where(Student.class_id == class_id and Student.group_id == nogroup.id))
        statics.selected = [False] * len(statics.students)

        statics.inited = True

    if statics.class_id != class_id:
        statics.inited = False

    center = imgui.get_main_viewport().get_center()
    imgui.set_next_window_pos(center, imgui.Cond_.appearing.value, ImVec2(0.5, 0.5))

    if imgui.begin_popup("Group", imgui.WindowFlags_.always_auto_resize.value):
        imgui_md.render_unindented("# New Group")

        _, statics.name = imgui.input_text("Name", statics.name)
        
        _, statics.project = imgui.input_text("Project", statics.project)

        for n, student in enumerate(statics.students):
            changed, _ = imgui.checkbox(f'{student.prename} {student.surname}', statics.selected[n])
            if changed:
                statics.selected[n] = not statics.selected[n]

        if imgui.button("Add"):
            if not statics.name:
                imgui.close_current_popup()
                imgui.end_popup()
                return False 

            if not statics.project:
                statics.project = "NoProject"

            group = Group.create(
                name = statics.name,
                project = statics.project,
                has_passed = False,
                class_id = class_id
            )
            
            students = list(compress(statics.students, statics.selected))
            if students:
                for student in students:
                    student.group_id = group.id
                with db.atomic():
                    Student.bulk_update(students, fields=[Student.group_id], batch_size=50)

            statics.inited = False
            imgui.close_current_popup()
            imgui.end_popup()
            return True

        imgui.same_line()
        
        if imgui.button("Cancel"):
            imgui.close_current_popup()
            statics.inited = False

        imgui.end_popup()

    return False


@immapp.static(inited=False)
def student_list(class_id: int) -> None:
    imgui_md.render_unindented('# Students')

    if class_id < 1:
        return
    
    statics = student_list
    if not statics.inited:
        statics.class_id = class_id
        statics.students = list(Student.select().where(Student.class_id == class_id))
        statics.inited = True
    
    if statics.class_id != class_id:
        statics.inited = False
   
    if imgui.button("Add Student"):
        imgui.open_popup("Student")
    
    if add_student(statics.class_id):
        statics.inited = False

    if imgui.begin_table("Students", 2, imgui.TableFlags_.sizing_fixed_fit.value):
        for n, student in enumerate(statics.students, start=1):
             
            imgui.table_next_row()
            imgui.table_next_column()
            
            if imgui.button(f"X##{student.surname}{student.id}"):
                Submission.delete().where(Submission.student_id == student.id).execute()
                student.delete_instance()
                statics.inited = False
                imgui.end_table()
                return

            imgui.same_line()
            imgui.text(f'{student.prename} {student.surname}')
            #imgui.table_next_column()
            #imgui.text(f"{group.project}")
        imgui.end_table()

from playhouse.shortcuts import model_to_dict
from pprint import pprint
@immapp.static(inited=False)
def add_student(class_id: int) -> bool:
    statics = add_student

    if not statics.inited:
        statics.class_id = class_id

        statics.prename = str()
        statics.surname = str()

        statics.genders = ["Male", "Female", "Diverse"]
        statics.gender_select = 0
        
        statics.studys = list(Study.select())
        statics.study_labels = [study.name for study in statics.studys]
        statics.study_select = 0 

        statics.groups = list(Group.select().where(Group.class_id == class_id))
        statics.group_labels = [group.name for group in statics.groups]
        statics.group_select = 0

        statics.graders = [grader.alt_name for grader in get_gradings()]
        statics.grader_select = 0
        
        statics.inited = True
    
    if statics.class_id != class_id or len(statics.studys) != Study.select().count() or len(statics.groups) != Group.select().where(Group.class_id == statics.class_id).count():
        statics.inited = False

    center = imgui.get_main_viewport().get_center()
    imgui.set_next_window_pos(center, imgui.Cond_.appearing.value, ImVec2(0.5, 0.5))

    if imgui.begin_popup("Student", imgui.WindowFlags_.always_auto_resize.value):
        imgui_md.render_unindented("# New Student")
        
        _, statics.prename = imgui.input_text("First Name", statics.prename)
        _, statics.surname = imgui.input_text("Last Name", statics.surname)
        
        imgui.text("Gender")
        for n, gender in enumerate(statics.genders):
            changed = imgui.radio_button(gender, statics.gender_select == n)
            if changed:
                statics.gender_select = n
        
        _, statics.study_select = imgui.combo("Study Progamm", statics.study_select, statics.study_labels)

        _, statics.group_select = imgui.combo("Group", statics.group_select, statics.group_labels)
        
        imgui.text("Grader")
        for n, grader in enumerate(statics.graders):
            changed = imgui.radio_button(grader, statics.grader_select == n)
            if changed:
                statics.grader_select = n

        if imgui.button("Add"):
            s = Student.create(
                prename = statics.prename,
                surname = statics.surname,
                sex = statics.genders[statics.gender_select],
                study_id = statics.studys[statics.study_select].id,
                class_id = class_id,
                group_id = statics.groups[statics.group_select].id,
                grader = statics.graders[statics.grader_select]
            )
            
            data = [
                {'student_id': s.id, 'lecture_id': lecture.id, 'class_id': s.class_id, 'points': 0.0}
                for lecture in Lecture.select().where(Lecture.class_id == s.class_id)
            ]
            Submission.insert_many(data).execute()

            statics.inited = False
            imgui.close_current_popup()
            imgui.end_popup()
            return True

        imgui.same_line()
        
        if imgui.button("Cancel"):
            imgui.close_current_popup()
            statics.inited = False

        imgui.end_popup()

    return False

@immapp.static(inited=False)
def study_list() -> None:
    statics = study_list

    if not statics.inited:
        statics.studys = Study.select().order_by(Study.id)
        statics.new_study = str()
        statics.inited = True
    
    imgui_md.render_unindented("# Study Programms")

    if imgui.button("Add Study"):
        Study.create(name=statics.new_study)
        statics.inited = False
    
    imgui.same_line()
    _, statics.new_study = imgui.input_text("##study", statics.new_study)

    if imgui.begin_table("Studys", 2, imgui.TableFlags_.sizing_fixed_fit.value):
        for study in statics.studys: 
            if study.name == 'Student':
                continue
            imgui.table_next_row()
            imgui.table_next_column()
            
            if imgui.button(f"X##{study.id}"):
                students = Student.select().where(Student.study_id == study.id)
                nostudy = Study.select().where(Study.name == "Student").get()
                for student in students:
                    student.study_id = nostudy.id
                with db.atomic():
                    Student.bulk_update(students, fields=[Student.study_id], batch_size=50)
                study.delete_instance()
                statics.inited = False
                imgui.end_table()
                return

            imgui.same_line()
            imgui.text(study.name)
            #imgui.table_next_column()
            #imgui.text(f"{group.project}")
        imgui.end_table()


def class_graph() -> None:
    if db.is_closed():
        imgui.text("No DB loaded")
        return

    w, h = imgui.get_content_region_avail()

    if imgui.begin_child("Group1", ImVec2(w, h*0.5)):        
        w1, h1 = imgui.get_content_region_avail()
        if imgui.begin_child("Groups", ImVec2(w1/3, h1), imgui.ChildFlags_.borders.value):
            group_list(state.class_id)
            imgui.end_child()
        
        imgui.same_line()

        if imgui.begin_child("Lectures", ImVec2(w1/3, h1), imgui.ChildFlags_.borders.value):
            lecture_list(state.class_id)
            imgui.end_child()
   
        imgui.same_line()

        if imgui.begin_child("Students", ImVec2(w1*0.32, h1), imgui.ChildFlags_.borders.value):
            student_list(state.class_id)
            imgui.end_child()
        imgui.end_child()

    if imgui.begin_child("Group2", ImVec2(w, h*0.5)):
        w1, h1 = imgui.get_content_region_avail()
        if imgui.begin_child("Ranking", ImVec2(w1/3, h1), imgui.ChildFlags_.borders.value):
            ranking(state.class_id)
            imgui.end_child()
        imgui.same_line()
        if imgui.begin_child("Studys", ImVec2(w1/3, h1), imgui.ChildFlags_.borders.value):
            study_list()
            imgui.end_child()
        imgui.end_child()
