<script setup lang="ts">
import { EMOJI_ABSENT, EMOJI_PRESENT, getDefaultEntry, type EntriesResponseStudent, type Entry, type EntryChecklistItem } from '@/api/classroom_compliance'
import { getFormattedDate } from '@/util';
import { computed, onMounted, ref, useTemplateRef, watch, type Ref } from 'vue'

const props = defineProps<{
  dateStr: string
  lastSaveStateTimestamp: number
  student: EntriesResponseStudent
  disabled?: boolean
}>()
defineEmits<{
  (e: 'editComment'): void
}>()

const model = defineModel<Entry | null>({
  required: false,
})
const checklistItemsByCategory: Ref<Record<string, EntryChecklistItem[]>> = computed(() => {
  if (!model.value) return {}
  const rec: Record<string, EntryChecklistItem[]> = {}
  for (const item of model.value.checklistItems) {
    if (!(item.category in rec)) {
      rec[item.category] = []
    }
    rec[item.category].push(item)
  }
  return rec
})
const initialEntryJson: Ref<string> = ref('')
const previouslyRemovedEntry: Ref<Entry | null> = ref(null)

const entryChanged = computed(() => JSON.stringify(model.value) !== initialEntryJson.value)
const hasComment = computed(() => model.value
  && (
    model.value.comment.trim().length > 0 ||
    model.value.checklistItems.filter(ck => ck.checked).length > 0
  ))

const previousCommentValue: Ref<string> = ref('')
const previousCommentChecklistItems: Ref<EntryChecklistItem[]> = ref([])
const cellEditorDialog = useTemplateRef('cellEditorDialog')

onMounted(() => {
  initialEntryJson.value = JSON.stringify(model.value)
  watch(
    () => props.lastSaveStateTimestamp,
    () => {
      initialEntryJson.value = JSON.stringify(model.value)
      previouslyRemovedEntry.value = null
    },
  )
})

function toggleAbsence() {
  if (model.value && !props.disabled) {
    model.value.absent = !model.value.absent
    if (model.value.absent) {
      // Remove additional data if student is absent.
      model.value.checklistItems = []
    } else {
      // Populate default additional data if student is no longer absent.
      // If we have an initial entry known, restore data from that.
      if (initialEntryJson.value) {
        const initialEntry = JSON.parse(initialEntryJson.value) as Entry
        if (initialEntry === null) return
        if (initialEntry.absent) return
        if (initialEntry.checklistItems.length > 0) {
          model.value.checklistItems.push(...initialEntry.checklistItems)
        }
      }
    }
  }
}

function showEditor() {
  if (!model.value) return
  previousCommentValue.value = model.value?.comment
  previousCommentChecklistItems.value = JSON.parse(JSON.stringify(model.value.checklistItems))
  cellEditorDialog.value?.showModal()
}

function clearEditor() {
  if (!model.value) return
  model.value.comment = ''
  for (const ck of model.value.checklistItems) {
    ck.checked = false
  }
}

function cancelEdit() {
  if (model.value) {
    model.value.comment = previousCommentValue.value
    model.value.checklistItems = previousCommentChecklistItems.value
  }
  cellEditorDialog.value?.close()
}

function removeEntry() {
  if (props.disabled) return
  if (model.value) {
    previouslyRemovedEntry.value = JSON.parse(JSON.stringify(model.value))
  }
  model.value = null
}

function addEntry() {
  if (props.disabled) return
  if (previouslyRemovedEntry.value) {
    model.value = JSON.parse(JSON.stringify(previouslyRemovedEntry.value))
  } else {
    model.value = getDefaultEntry(props.dateStr)
  }
}
</script>
<template>
  <td :class="{ absent: model?.absent, changed: entryChanged, 'missing-entry': !model }">
    <div v-if="model" class="cell-container">
      <div>
        <div class="status-item" :class="{ 'status-item-disabled': disabled }" @click="toggleAbsence">
          <span v-if="model.absent" title="Absent">{{ EMOJI_ABSENT }}</span>
          <span v-if="!model.absent" title="Present">{{ EMOJI_PRESENT }}</span>
        </div>
        <!--
        <div class="status-item" :class="{ 'status-item-disabled': disabled }" @click="toggleClassroomReadiness"
          v-if="!model.absent && model.classroomReadiness !== null">
          <span v-if="model.classroomReadiness" title="Ready for Class">{{ EMOJI_CLASSROOM_READY }}</span>
          <span v-if="!model.classroomReadiness" title="Not Ready for Class">{{ EMOJI_NOT_CLASSROOM_READY }}</span>
        </div>
        <div class="status-item" :class="{ 'status-item-disabled': disabled }" @click="toggleBehaviorRating"
          v-if="!model.absent">
          <span v-if="model.behaviorRating === 3" title="Good Behavior">{{ EMOJI_BEHAVIOR_GOOD }}</span>
          <span v-if="model.behaviorRating === 2" title="Mediocre Behavior">{{ EMOJI_BEHAVIOR_MEDIOCRE }}</span>
          <span v-if="model.behaviorRating === 1" title="Poor Behavior">{{ EMOJI_BEHAVIOR_POOR }}</span>
        </div>
        -->
        <div class="status-item" @click="showEditor">
          <span v-if="hasComment"
            style="position: relative; float: right; top: 0px; right: 5px; font-size: 6px;">🔴</span>
          <span title="Comments">💬</span>
        </div>
      </div>
      <div>
        <div class="status-item" @click="removeEntry">
          <span>🗑️</span>
        </div>
      </div>
    </div>

    <div v-if="model === null && !disabled">
      <div class="status-item" @click="addEntry">
        <span>+</span>
      </div>
    </div>

    <!-- A comment editor dialog that shows up when the user edits their comment. -->
    <dialog ref="cellEditorDialog" v-if="model">
      <h2 style="margin-top: 0;">
        Entry for {{ student.name }} on {{ getFormattedDate(dateStr) }}
        <span v-if="model.absent" style="color: gray;">Absent</span>
      </h2>
      <!-- First part of the editor has each category of checklist items. -->
      <div style="display: flex; flex-direction: row;">
        <div v-for="options, category in checklistItemsByCategory" :key="category"
          style="flex-grow: 1; margin: 0 1rem;">
          <h3 style="margin-top: 0;">{{ category }}</h3>
          <label v-for="opt in options" :key="opt.item" style="margin: 0.25rem 0;">
            <input type="checkbox" v-model="opt.checked" :value="opt" :disabled="disabled || model.absent" />
            <span style="margin-left: 0.25rem;" :style="{ 'color': model.absent ? 'gray' : 'inherit' }">
              {{ opt.item }}
            </span>
          </label>
        </div>
      </div>
      <!-- Then below that, comments. -->
      <div>
        <h3>Comments</h3>
        <textarea v-model="model.comment" style="min-width: 300px; min-height: 100px;"
          @keydown.enter="cellEditorDialog?.close()" :readonly="disabled"></textarea>
      </div>

      <div class="button-bar" style="text-align: right;">
        <button type="button" @click="cellEditorDialog?.close()" :disabled="disabled">Confirm</button>
        <button type="button" @click="clearEditor" :disabled="disabled">Clear</button>
        <button type="button" @click="cancelEdit">Cancel</button>
      </div>
    </dialog>
  </td>
</template>
<style scoped>
td {
  border: 1px solid black;
  border-collapse: collapse;
}

.missing-entry {
  text-align: right;
}

.absent {
  color: blue;
  border: 1px solid black;
}

.changed {
  border: 2px solid orange !important;
}

.status-item {
  display: inline-block;
  cursor: pointer;
}

.status-item-disabled {
  cursor: default !important;
}

.status-item+.status-item {
  margin-left: 0.5em;
}

.cell-container {
  display: flex;
  justify-content: space-between;
  padding: 0.25em;
}
</style>
