<script>
import { shallowRef, computed, watch, provide } from 'vue';
import { cmp, add, sub, timedelta, Date } from '@silane/datetime';

import { inject, keys as injectionKeys } from '../../injection';
import {
  useLocalStorage, useSessionStorage,
} from '../../composables/webstorage';
import {
  useGeneralTimetableScope
} from '../../composables/general-timetable-scope';
import {
  useGeneralTimetableScopeHistory
} from '../../composables/general-timetable-scope-history';


export default {
  name: 'PageMasterTimetable',
  setup() {
    const today = Date.today();

    const notification = inject(injectionKeys.notification);
    const resourceStore = inject(injectionKeys.resourceStore);

    const localStorage = useLocalStorage();
    const sessionStorage = useSessionStorage();
    const generalTimetableScope = useGeneralTimetableScope(
      localStorage, sessionStorage
    );
    const generalTimetableScopeHistory = useGeneralTimetableScopeHistory(
      localStorage, generalTimetableScope, 5
    );

    provide(injectionKeys.generalTimetableScope, generalTimetableScope);

    const classrooms = computed(() => resourceStore.resources.value.filter(
      x => x.type === 'classroom' && !x.disabled
    ));

    const classroom = shallowRef(
      /** @type {import('../../composables/resourcestore').Resource | null} */(null)
    );
    const dateRange = shallowRef(/** @type {[Date, Date]} */([
      today, add(today, timedelta({ days: 1 }))
    ]));

    function loadTimetableScope() {
      classroom.value = classrooms.value.find(
        x => x.id === generalTimetableScope.classroom.value
      ) ?? null;
      if(!classroom.value) {
        const newClassroom = classrooms.value[0] ?? null;
        classroom.value = newClassroom;
        if(newClassroom ?? '' !== generalTimetableScope.classroom.value) {
          submitTimetableScope();
        }
      }
      const newDateRange = [...generalTimetableScope.dateRange.value];
      if(cmp(newDateRange[0], newDateRange[1]) >= 0) {
        newDateRange[1] = add(newDateRange[0], timedelta({ days: 1 }));
        dateRange.value = newDateRange;
        submitTimetableScope();
      } else {
        dateRange.value = newDateRange;
      }
    }

    watch([
      generalTimetableScope.classroom, generalTimetableScope.dateRange,
    ], () => { loadTimetableScope(); }, { immediate: true });

    watch(classrooms, () => {
      classroom.value = classrooms.value[0] ?? null;
    }, { immediate: true });

    const timetableScopeModified = computed(() => (
      (classroom.value?.id ?? '') !== generalTimetableScope.classroom.value
    ) || dateRange.value.some(
      (v, i) => cmp(v, generalTimetableScope.dateRange.value[i]) !== 0
    ));

    function submitTimetableScope() {
      if(cmp(dateRange.value[0], dateRange.value[1]) >= 0) {
        notification.add('error', '開始日付が終了日付より後です。');
        return;
      }
      if(cmp(
        sub(dateRange.value[1], dateRange.value[0]), timedelta({ weeks: 12 })
      ) > 0) {
        notification.add('error', '開始日付と終了日付は12週間以内である必要があります。');
        return;
      }
      generalTimetableScope.setClassroom(classroom.value?.id ?? '');
      generalTimetableScope.setDateRange(dateRange.value);
    }

    const timetableScopeHistories = computed(() => (
      generalTimetableScopeHistory.history.value.map(x => ({
        ...x, classroom: classrooms.value.find(
          classroom => classroom.id === x.classroom
        )
      })).filter(x => x.classroom)
    ));

    const selectedTimetableScopeHistory = shallowRef(
      /** @type{(typeof timetableScopeHistories.value)[number] | null} */(null)
    );
    watch(selectedTimetableScopeHistory, async () => {
      if(selectedTimetableScopeHistory.value == null) return null;
      classroom.value = selectedTimetableScopeHistory.value.classroom;
      dateRange.value = selectedTimetableScopeHistory.value.dateRange;
      submitTimetableScope();
    });

    return {
      classrooms, classroom, dateRange, timetableScopeModified,
      timetableScopeHistories, selectedTimetableScopeHistory,
      submitTimetableScope, loadTimetableScope,
    };
  },
}
</script>

<template>
<p v-if="classroom == null">
  教室が一つも登録されていません。
  <router-link to="/master/config/classroom">ここ</router-link>から最低一つ教室を登録してください。
</p>
<template v-else>
<section class="timetablescopesettings">
  <h1 class="timetablescopesettings-header">スコープ</h1>
  <label>
    履歴:
    <select v-model="selectedTimetableScopeHistory">
      <option :value="null">-</option>
      <option
        v-for="historyItem of timetableScopeHistories" :value="historyItem"
      >
        {{ `${historyItem.classroom.label} ${
          historyItem.dateRange.map(x => x.strftime('%Y/%m/%d')).join('～')
        }` }}
      </option>
    </select>
  </label>
  <label class="timetablescopesettings-settingitem">
    表示教室:
    <select v-model="classroom">
      <option
        v-for="resource of classrooms" :key="resource.id" :value="resource"
      >{{ resource.label }}</option>
    </select>
  </label>
  <label class="timetablescopesettings-settingitem">
    表示日付範囲:
    <InputDateRange style="width: fit-content;" v-model="dateRange" />
  </label>
  <template v-if="timetableScopeModified">
    <button
      type="button" @click="
        submitTimetableScope();
        selectedTimetableScopeHistory = null;
      " class="submittimetablescopebutton"
    >適用する</button>
    <button type="button" @click="loadTimetableScope()">元に戻す</button>
  </template>
</section>
<router-view />
</template>
</template>

<style scoped>
.timetablescopesettings {
  padding: .25em .5em;
  border: solid 1px black;
  border-radius: .5em;
  display: flex;
  flex-wrap: wrap;
  gap: .4em .8em;
  align-items: center
}
.timetablescopesettings-header {
  display: none;
}
.timetablescopesettings-settingitem {
  display: flex;
  align-items: center;
  gap: .2em;
}

@keyframes submittimetablescopebuttonanimation {
  0% {
    filter: invert(0%);
  }
  49% {
    filter: invert(0%);
  }
  50% {
    filter: invert(100%)
  }
  99% {
    filter: invert(100%)
  }
  100% {
    filter: invert(0%);
  }
}
.submittimetablescopebutton {
  animation: submittimetablescopebuttonanimation 1.5s infinite;
}
</style>
