<script setup lang="ts">

import {computed, onMounted, reactive, ref, toRaw, watch} from "vue";
import TablePlan from "@/components/TablePlan.vue";
import {API} from "@/services/api";
import type {Gottesdienst, GottesdienstGroup, Mark, SimplifiedMinistrant} from "@/models/models";
import MobilePlan from "@/components/MobilePlan.vue";
import PlanActionBar from "@/components/PlanActionBar.vue";
import {Auth} from "@/services/auth";
import GroupView from "@/components/GroupView.vue";
import {Dialogs} from "@/services/DialogService";
import ConfirmDialog from "@/components/dialog/ConfirmDialog.vue";
import CreatePlanDialog from "@/components/dialog/CreatePlanDialog.vue";
import CreateGottesdienstDialog from "@/components/dialog/CreateGottesdienstDialog.vue";
import CreateMinistrantDialog from "@/components/dialog/CreateMinistrantDialog.vue";
import {useRoute, useRouter} from "vue-router";
import {min} from "rxjs";

const MAX_WIDTH_MOBILE = 600;

const router = useRouter()
const route = useRoute()

const plan = reactive<{
    gottesdienste: Gottesdienst[],
    ministranten: SimplifiedMinistrant[],
    marks: Mark[],
    editable: string[],
    groups: GottesdienstGroup[]
}>({
    gottesdienste: [],
    ministranten: [],
    marks: [],
    editable: [],
    groups: []
})
const mobile = ref(window.innerWidth <= MAX_WIDTH_MOBILE)
const editedMarks = reactive<Mark[]>([]);
const editPlanAdmin = ref(false)
const planId = ref(parseInt(route.params.id as string))


onMounted(async () => {
    const groups = await API.getPlans()
    console.log("Groups", groups)
    plan.groups = groups
    loadPlan()
})

watch(() => route.params.id, async (value, oldValue) => {
    planId.value = parseInt(value as string)
    await loadPlan()
})

async function loadPlan() {
    const { ministranten, gottesdienste, marks} = await API.getPlan(planId.value)
    plan.ministranten = ministranten
    plan.gottesdienste = gottesdienste
    plan.marks = marks
    Auth.checkForToken()
}

Auth.loggedInSubject.subscribe(async (loggedIn) => {
    console.log("logged in " + loggedIn)
    if (loggedIn) {
        plan.editable = Auth.getPrivileges()
        if (Auth.getUser() == "admin") {
            editPlanAdmin.value = true
            plan.ministranten = await API.getMinistranten();
            console.log("Plan", plan.ministranten)
        }
    } else {
        editPlanAdmin.value = false
        plan.editable = []
    }
})

window.addEventListener("resize", (ev) => {
    mobile.value = window.innerWidth <= MAX_WIDTH_MOBILE
})


const sortedGottesdienste = computed(() => {
    return plan.gottesdienste.sort((a, b) => {
        return a.date - b.date
    })
})

async function createGottesdienst(){
    Dialogs.createDialog(CreateGottesdienstDialog, {
        onPositive() {},
        onNegative() {},
        onDismiss() {}
    }, {
        planId: parseInt(planId.value as string),
        async onCreate(godi: Gottesdienst) {
            const newGodi = await API.addGottesdienst(
                godi.name,
                godi.date,
                godi.attendance,
                godi.planId
            )
            plan.gottesdienste.push(newGodi)
        }
    })
}

async function addGodi(data, validate) {
    console.log("Test")
    console.log(data)
    let date = Date.parse(data.date + "T" + data.time);
    let attendance = data.attendance && data.attendance != ""
        ? Date.parse(data.date + "T" + data.attendance)
        : (date - 1000 * 60 * 30)
    console.log(date, attendance, data.date + "T" + data.attendance)
    let newGodi = await API.addGottesdienst(
        data.name,
        new Date(date),
        new Date(attendance),
        parseInt(planId.value as string)
    )
    console.log(newGodi)
    plan.gottesdienste.push(newGodi);
    validate()
}

async function deleteGottedienst(id) {
    let deleted = await API.deleteGottesdienst(id)
    if (deleted) {
        let index = plan.gottesdienste.findIndex(godi => godi.id == id)
        plan.gottesdienste.splice(index, 1)
    }
}


function getMarks(): Mark[] {
    return plan.marks.filter((mark: Mark) => {
        let difMark = editedMarks.find((m: Mark) => m.gid == mark.gid && m.mid == mark.mid)
        return !difMark
    }).concat(editedMarks);
}

function getDif(): Mark[] {
    return editedMarks.filter((mark: Mark) => {
        let sameMark = plan.marks.find((m: Mark) => m.gid == mark.gid && m.mid == mark.mid)
        return (!sameMark && mark.value != 0) || (sameMark && mark.value != sameMark.value)
    })
}

async function saveChanges() {
    const saved = await API.setMarks(getDif())
    if (saved) {
        plan.marks = getMarks()
        editedMarks.length = 0
    }
}

async function resetPassword(username: string) {
    const result = await API.resetPassword(username)
    alert("Neues Passwort für " + username + "\n\n" + result.password)
    console.log(result)
}

function canEdit(username: string) {
    return plan.editable.includes(username)
}

function toggleMark(gid, mid) {
    // TODO: track changes
    const username = plan.ministranten.find(m => m.id == mid)?.username
    if (!canEdit(username)) return;

    let mark = editedMarks.find(m => m.mid == mid && m.gid == gid);
    if (mark) {
        mark.value = ((mark.value + 2) % 3) - 1
    } else {
        mark = {
            gid, mid, value: 1
        }
        editedMarks.push(mark)
    }
}


async function createNewPlan() {
    Dialogs.createDialog(CreatePlanDialog, {
        onPositive: () => {},
        onNegative: () => {},
        onDismiss: () => {},
    }, {
        onCreate: async (group: GottesdienstGroup) => {
            const newPlan = await API.createPlan(new Date(group.from).getTime(), new Date(group.to).getTime());
            plan.groups = [newPlan].concat(toRaw(plan.groups))
            router.replace("/" + newPlan.id)
        }
    })
}

async function deletePlan(id) {
    if(!confirm("Möchtest du den Plan wirklich löschen?")) return
    await API.deletePlan(id)
    location.reload()
    plan.groups.splice(plan.groups.findIndex(g => g.id == id), 1)
}

async function editPlan(id) {
    const group = Object.assign({}, toRaw(plan.groups.find(g => g.id == id)))
    group.from = new Date(group.from).toISOString().substring(0,10)
    group.to = new Date(group.to).toISOString().substring(0,10)
    Dialogs.createDialog(CreatePlanDialog, {
        onPositive() {},
        onNegative() {},
        onDismiss() {}
    }, {
        group,
        async onCreate(group) {
            group.from = new Date(group.from).getTime()
            group.to = new Date(group.to).getTime()
            await API.updatePlan(group)
            location.reload()
        }
    })
}

async function createMinistrant(ministrantId?: number) {
    let ministrantRef = plan.ministranten.find(ministrant => ministrant.id == ministrantId)
    const ministrant = ministrantRef ? Object.assign({}, toRaw(ministrantRef)) : null;
    console.log("Found mini ref?", ministrant)
    Dialogs.createDialog(CreateMinistrantDialog, {
        onPositive() {},
        onNegative() {},
        onDismiss() {}
    }, {
        ministrant,
        async onCreate(ministrant) {
            ministrant.birthday = ministrant.birthday.getTime()
            if(ministrant.id == -1) {
                const newMinistrant = await API.createMinistrant(ministrant)
                ministrant.id = newMinistrant.id
                plan.ministranten.push(ministrant)
            }else {
                await API.updateMinistrant(ministrant)
                const index = plan.ministranten.findIndex(m => m.id == ministrant.id)
                plan.ministranten.splice(index, 1)
                plan.ministranten.push(ministrant)
            }
        },
        async onDelete(id) {
            let deleted = await API.deleteMinistrant(id)
            if (deleted) {
                let index = plan.ministranten.findIndex(godi => godi.id == id)
                plan.ministranten.splice(index, 1)
            }
        }
    })
}



</script>

<template>
    <main>

        <div class="container">

            <GroupView :groups="plan.groups" :admin="editPlanAdmin"
                       @new="createNewPlan" @delete="deletePlan" @edit="editPlan" class="no-print"/>
            <TablePlan
                :gottesdienste="sortedGottesdienste"
                :ministranten="plan.ministranten"
                :marks="getMarks()"
                :editable="plan.editable"
                :edit="editPlanAdmin"
                :small-mode="editPlanAdmin"
                @added="addGodi"
                @delete="deleteGottedienst"
                @toggle-mark="toggleMark"
                @end-edit="editPlanAdmin = false"
                @reset-password="resetPassword"
                @create-ministrant="createMinistrant"
                @edit-ministrant="createMinistrant"
                class="plan table"
                v-if="!mobile">

            </TablePlan>

            <MobilePlan
                :gottesdienste="sortedGottesdienste"
                :ministranten="plan.ministranten"
                :marks="getMarks()"
                :editable="plan.editable"
                @toggle-mark="toggleMark"
                class="plan mobile"
                v-else>

            </MobilePlan>

            <PlanActionBar
                class="action-bar no-print"
                :save="getDif().length > 0"
                :plan="false"
                :godi="true"
                @save="saveChanges()"
                @add-godi="createGottesdienst()"
                @add-mini="createMinistrant()"
                v-if="editPlanAdmin"
            />
        </div>
    </main>
</template>


<style scoped lang="less">

.container {
    width: 100%;
    overflow-x: auto;

    @media print {
        overflow-x: unset;
    }
}

.plan {
    padding-bottom: 100px;
}

.plan.table {
    //width: 100%;
}

.action-bar {
    position: fixed;
    bottom: 0;
    z-index: 100;
}
</style>
