<template>
  <CloudIcon v-if="syncing == 'synced'" class="w-5 h-5" />
  <CloudArrowUpIcon
    v-else-if="syncing == 'detectedChanges'"
    class="w-5 h-5 cursor-pointer animate-bounce"
    @click="syncAll"
  />
  <ArrowPathIcon v-else-if="syncing == 'syncing'" class="w-5 h-5 animate-spin" />
  <ExclamationTriangleIcon
    v-else
    class="w-5 h-5 animate-[ping_1s_ease-in-out_3] text-red-500 cursor-pointer"
    @click="syncAll"
  />
</template>

<script setup lang="ts">
import { defineComponent } from "vue";
import { mapState, mapActions } from "pinia";
import { useProtocolStore } from "@/stores/admin/protocol";
import { ArrowPathIcon, CloudArrowUpIcon, CloudIcon, ExclamationTriangleIcon } from "@heroicons/vue/24/outline";
import { useProtocolAgendaStore } from "@/stores/admin/protocolAgenda";
import { useProtocolPresenceStore } from "@/stores/admin/protocolPresence";
import { useProtocolDecisionStore } from "@/stores/admin/protocolDecision";
import { useProtocolVotingStore } from "@/stores/admin/protocolVoting";
</script>

<script lang="ts">
export default defineComponent({
  props: ["executeSyncAll"],
  watch: {
    executeSyncAll() {
      this.syncAll();
    },
    syncing() {
      this.$emit("syncState", this.syncing);
    },
    detectedChangeProtocol() {
      clearTimeout(this.protocolTimer);
      this.setProtocolSyncingState("synced");
      if (this.detectedChangeProtocol == false) {
        return;
      }
      this.setProtocolSyncingState("detectedChanges");
      this.protocolTimer = setTimeout(() => {
        this.synchronizeActiveProtocol();
      }, 10000);
    },
    detectedChangeProtocolAgenda() {
      clearTimeout(this.protocolAgendaTimer);
      if (this.detectedChangeProtocolAgenda == false) {
        this.setProtocolAgendaSyncingState("synced");
        return;
      }
      this.setProtocolAgendaSyncingState("detectedChanges");
      this.protocolAgendaTimer = setTimeout(() => {
        this.synchronizeActiveProtocolAgenda();
      }, 10000);
    },
    detectedChangeProtocolPresence() {
      clearTimeout(this.protocolPresenceTimer);
      this.setProtocolPresenceSyncingState("synced");
      if (this.detectedChangeProtocolPresence == false) {
        return;
      }
      this.setProtocolPresenceSyncingState("detectedChanges");
      this.protocolPresenceTimer = setTimeout(() => {
        this.synchronizeActiveProtocolPresence();
      }, 10000);
    },
    detectedChangeProtocolDecision() {
      clearTimeout(this.protocolDecisionTimer);
      this.setProtocolDecisionSyncingState("synced");
      if (this.detectedChangeProtocolDecision == false) {
        return;
      }
      this.setProtocolDecisionSyncingState("detectedChanges");
      this.protocolDecisionTimer = setTimeout(() => {
        this.synchronizeActiveProtocolDecision();
      }, 10000);
    },
    detectedChangeProtocolVoting() {
      clearTimeout(this.protocolVotingTimer);
      this.setProtocolVotingSyncingState("synced");
      if (this.detectedChangeProtocolVoting == false) {
        return;
      }
      this.setProtocolVotingSyncingState("detectedChanges");
      this.protocolVotingTimer = setTimeout(() => {
        this.synchronizeActiveProtocolVoting();
      }, 10000);
    },
  },
  emits: {
    syncState(state: "synced" | "syncing" | "detectedChanges" | "failed") {
      return typeof state == "string";
    },
  },
  data() {
    return {
      protocolTimer: undefined as undefined | any,
      protocolAgendaTimer: undefined as undefined | any,
      protocolPresenceTimer: undefined as undefined | any,
      protocolDecisionTimer: undefined as undefined | any,
      protocolVotingTimer: undefined as undefined | any,
    };
  },
  mounted() {
    this.$emit("syncState", this.syncing);
  },
  beforeUnmount() {
    if (!this.protocolTimer) clearTimeout(this.protocolTimer);
    if (!this.protocolAgendaTimer) clearTimeout(this.protocolAgendaTimer);
    if (!this.protocolPresenceTimer) clearTimeout(this.protocolPresenceTimer);
    if (!this.protocolDecisionTimer) clearTimeout(this.protocolDecisionTimer);
    if (!this.protocolVotingTimer) clearTimeout(this.protocolVotingTimer);
  },
  computed: {
    ...mapState(useProtocolStore, ["syncingProtocol", "detectedChangeProtocol"]),
    ...mapState(useProtocolAgendaStore, ["syncingProtocolAgenda", "detectedChangeProtocolAgenda"]),
    ...mapState(useProtocolPresenceStore, ["syncingProtocolPresence", "detectedChangeProtocolPresence"]),
    ...mapState(useProtocolDecisionStore, ["syncingProtocolDecision", "detectedChangeProtocolDecision"]),
    ...mapState(useProtocolVotingStore, ["syncingProtocolVoting", "detectedChangeProtocolVoting"]),

    syncing(): "synced" | "syncing" | "detectedChanges" | "failed" {
      let states = [
        this.syncingProtocol,
        this.syncingProtocolAgenda,
        this.syncingProtocolPresence,
        this.syncingProtocolDecision,
        this.syncingProtocolVoting,
      ];

      if (states.includes("failed")) return "failed";
      else if (states.includes("syncing")) return "syncing";
      else if (states.includes("detectedChanges")) return "detectedChanges";
      else return "synced";
    },
  },
  methods: {
    ...mapActions(useProtocolStore, ["synchronizeActiveProtocol", "setProtocolSyncingState"]),
    ...mapActions(useProtocolAgendaStore, ["synchronizeActiveProtocolAgenda", "setProtocolAgendaSyncingState"]),
    ...mapActions(useProtocolPresenceStore, ["synchronizeActiveProtocolPresence", "setProtocolPresenceSyncingState"]),
    ...mapActions(useProtocolDecisionStore, ["synchronizeActiveProtocolDecision", "setProtocolDecisionSyncingState"]),
    ...mapActions(useProtocolVotingStore, ["synchronizeActiveProtocolVoting", "setProtocolVotingSyncingState"]),

    syncAll() {
      if (!this.protocolTimer) clearTimeout(this.protocolTimer);
      if (!this.protocolAgendaTimer) clearTimeout(this.protocolAgendaTimer);
      if (!this.protocolPresenceTimer) clearTimeout(this.protocolPresenceTimer);
      if (!this.protocolDecisionTimer) clearTimeout(this.protocolDecisionTimer);
      if (!this.protocolVotingTimer) clearTimeout(this.protocolVotingTimer);

      this.synchronizeActiveProtocol();
      this.synchronizeActiveProtocolAgenda();
      this.synchronizeActiveProtocolPresence();
      this.synchronizeActiveProtocolDecision();
      this.synchronizeActiveProtocolVoting();
    },
  },
});
</script>
