<template>
  <div v-if="visible" class="dialog-overlay">
    <div class="dialog">
      <h1 class="text-xl font-bold text-center mb-4">Here's one:</h1>
      <span class="flex justify-between">
        <span
          class="rounded-l border border-slate-400 bg-slate-200 px-4 py-2 flex"
          @click="prevIdea()"
        >
          <fa icon="chevron-left" class="m-auto" />
        </span>

        <div class="m-2">
          <span v-if="currentIdeaIndex < IDEAS.length">
            <p class="text-center text-lg font-bold">
              {{ IDEAS[currentIdeaIndex] }}
            </p>
          </span>
          <div v-if="currentIdeaIndex == IDEAS.length + 0">
            <p class="text-center">
              <span
                v-if="currentContact == null"
                class="text-orange-500 text-lg font-bold"
              >
                That's all your contacts.
              </span>
              <span v-else>
                <span class="text-lg font-bold">
                  Did {{ currentContact.name || AppString.NO_CONTACT_NAME }}
                  <br />
                  or someone near them do anything &ndash; maybe a while ago?
                </span>
                <span class="flex justify-between">
                  <span />
                  <button
                    class="text-center bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4"
                    @click="nextIdeaPastContacts()"
                  >
                    Skip Contacts <fa icon="forward" />
                  </button>
                </span>
              </span>
            </p>
          </div>
        </div>

        <span
          class="rounded-r border border-slate-400 bg-slate-200 px-4 py-2 flex"
          @click="nextIdea()"
        >
          <fa icon="chevron-right" class="m-auto" />
        </span>
      </span>
      <button
        class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mt-4"
        @click="cancel"
      >
        That's it!
      </button>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from "vue-facing-decorator";

import { AppString, NotificationIface } from "@/constants/app";
import { db } from "@/db/index";
import { Contact } from "@/db/tables/contacts";

@Component
export default class GivenPrompts extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  IDEAS = [
    "Did anyone fix food for you?",
    "Did a family member do something for you?",
    "Did anyone give you a compliment?",
    "Who is someone you can always rely on, and how did they demonstrate that?",
    "Did you see anyone give to someone else?",
    "Is there someone who you have never met who has helped you somehow?",
    "How did an artist or musician or author inspire you?",
    "What inspiration did you get from someone who handled tragedy well?",
    "Did some organization give something worth respect?",
    "Who last gave you a good laugh?",
    "Do you recall anything that was given to you while you were young?",
    "Did someone forgive you or overlook a mistake?",
    "Do you know of a way an ancestor contributed to your life?",
    "Did anyone give you help at work?",
    "How did a teacher or mentor or great example help you?",
  ];
  OTHER_PROMPTS = 1;
  CONTACT_PROMPT_INDEX = this.IDEAS.length; // expected after other prompts

  currentContact: Contact | undefined = undefined;
  currentIdeaIndex = 0;
  numContacts = 0;
  shownContactDbIndices: number[] = [];
  visible = false;

  AppString = AppString;

  async open() {
    this.visible = true;

    await db.open();
    this.numContacts = await db.contacts.count();
  }

  close() {
    // close the dialog but don't change values (just in case some actions are added later)
    this.visible = false;
  }

  /**
   * Get the next idea.
   * If it is a contact prompt, loop through.
   */
  async nextIdea() {
    // if we're incrementing to the contact prompt
    // or if we're at the contact prompt and there was a previous contact...
    if (
      this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX - 1 ||
      (this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX &&
        this.shownContactDbIndices.length < this.numContacts)
    ) {
      this.currentIdeaIndex = this.CONTACT_PROMPT_INDEX;
      this.findNextUnshownContact();
    } else {
      // we're not at the contact prompt (or we ran out), so increment the idea index
      this.currentIdeaIndex =
        (this.currentIdeaIndex + 1) % (this.IDEAS.length + this.OTHER_PROMPTS);
      // ... and clear out any other prompt info
      this.currentContact = undefined;
      this.shownContactDbIndices = [];
    }
  }

  prevIdea() {
    if (
      this.currentIdeaIndex ==
        (this.CONTACT_PROMPT_INDEX + 1) %
          (this.IDEAS.length + this.OTHER_PROMPTS) ||
      (this.currentIdeaIndex == this.CONTACT_PROMPT_INDEX &&
        this.shownContactDbIndices.length < this.numContacts)
    ) {
      this.currentIdeaIndex = this.CONTACT_PROMPT_INDEX;
      this.findNextUnshownContact();
    } else {
      // we're not at the contact prompt (or we ran out), so increment the idea index
      this.currentIdeaIndex--;
      if (this.currentIdeaIndex < 0) {
        this.currentIdeaIndex = this.IDEAS.length - 1 + this.OTHER_PROMPTS;
      }
      // ... and clear out any other prompt info
      this.currentContact = undefined;
      this.shownContactDbIndices = [];
    }
  }

  nextIdeaPastContacts() {
    this.currentIdeaIndex = 0;
    this.currentContact = undefined;
    this.shownContactDbIndices = [];
  }

  async findNextUnshownContact() {
    // get a random contact
    if (this.shownContactDbIndices.length === this.numContacts) {
      // no more contacts to show
      this.currentContact = undefined;
    } else {
      // get a random contact that hasn't been shown yet
      let someContactDbIndex = Math.floor(Math.random() * this.numContacts);
      // and guarantee that one is found by walking past shown contacts
      let shownContactIndex =
        this.shownContactDbIndices.indexOf(someContactDbIndex);
      while (shownContactIndex !== -1) {
        // increment both indices until we find a spot where "shown" skips a spot
        shownContactIndex = (shownContactIndex + 1) % this.numContacts;
        someContactDbIndex = (someContactDbIndex + 1) % this.numContacts;
        if (
          this.shownContactDbIndices[shownContactIndex] !== someContactDbIndex
        ) {
          // we found a contact that hasn't been shown yet
          break;
        }
        // continue
        // ... and there must be at least one because shownContactDbIndices length < numContacts
      }
      this.shownContactDbIndices.push(someContactDbIndex);
      this.shownContactDbIndices.sort();

      // get the contact at that offset
      await db.open();
      this.currentContact = await db.contacts
        .offset(someContactDbIndex)
        .first();
    }
  }

  cancel() {
    this.currentContact = undefined;
    this.currentIdeaIndex = 0;
    this.numContacts = 0;
    this.shownContactDbIndices = [];

    this.close();
  }
}
</script>

<style>
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1.5rem;
}

.dialog {
  background-color: white;
  padding: 1rem;
  border-radius: 0.5rem;
  width: 100%;
  max-width: 500px;
}
</style>
