<!--
  Root component for the Todo app that is displayed if the user is logged in.

  Part of the basebox sample Todo app.
  https://basebox.io
-->
<template>

  <main>

    <h1>
      ToDo List
    </h1>

    <div id="filter-form" class="toolbar">

      <label class="switch">
        <input type="checkbox" v-model="showCompleted">
        Show completed
      </label>

      <button type="button" @click="addTask()" class="ms-auto btn btn-primary btn-large">Add Item</button>

      <div class="ms-auto">
        <div class="d-flex">
          <label class="col-form-label" for="list-selector">Select List: </label>
          <div class="ms-2">
            <select id="list-selector" class="form-select" v-model="currentList">
              <option :value="0" selected>All</option>
              <option v-for="item in gStore.lists" :key="item.id" :value="item.id">{{ item.title }}</option>
            </select>
          </div>
        </div>
      </div>
    </div>

    <div id="todo-container">

      <transition-group name="list" tag="div">
        <div :class="todoItemClass(task)" v-for="(task, i) in filteredItems" :id="'task-' + task.id" :key="task.id">
          <div :class="todoCheckedClass(task)" @click="toggleCompleted(task)">
            &nbsp;
          </div>
          <div class="item-v-container">
            <input class="item-title" type="text" @blur="saveTask(task)" v-model="task.title">
            <input class="todo-description" type="text" @blur="saveTask(task)" v-model="task.description">
          </div>
          <div class="item-meta">
            <div class="dropdown">
              <button class="btn btn-sm btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
                <i class="bi bi-trash"></i>
              </button>
              <ul class="dropdown-menu">
                <li><a class="dropdown-item" href="" @click="deleteTask(task)">Delete this item</a></li>
              </ul>
            </div>
          </div>
        </div>

        <div class="alert alert-info" v-if="filteredItems.length === 0">
          <p><i class="bi bi-info-circle"></i>
            Sorry, there are no todo items{{ currentList !== 0 ? " in this list" : ""}}.
          </p>
          <p v-if="currentList !== 0">You can add items or select another list.</p>
          <hr>
          <button type="button" class="btn btn-primary btn-sm" @click="addTask()">Create Todo Item</button>
        </div>

      </transition-group>
    </div>

  </main>
</template>

<script>
import { gqlRequest } from "../util/net";
import { removeTask, showError, store } from "../store";
import { showModal } from "../util/misc";

const NEW_TASK_ID = "new-task-id";

export default {
  name: "Todo",
  components: [],

  /** Current state of the component */
  data() {
    return {
      /** whether to show completed items */
      showCompleted: true,
      /* the id of the list currently being shown */
      currentList: 0,
    }
  },

  methods: {

    /**
     * Save a task to the database.
     * @param task the task to save; this is an object as received from the broker.
     */
    saveTask(task) {
      console.info(`Saving task '${task.title}' with id ${task.id}`);
      let request = "";
      if (task.id !== NEW_TASK_ID) {
        /* save changes to existing task */
        request = `mutation {
          updateTask(
            id: "${task.id}",
            title: "${task.title}",
            description: "${task.description}",
            completed: ${task.completed ? "true" : "false"},
            list: {
              id: "${task.list.id}"
            },
          ) {
            id
          }
        }`;
      } else {
        /* create new task */
        request = `mutation {
          createTask(
            title: "${task.title}",
            description: "${task.description}",
            completed: ${task.completed ? "true" : "false"},
            list: {
              id: "${task.list.id}"
            },
            user: {
              username: "${store.userId}"
            }
          ) {
            id
          }
        }`;
      }

      /* send query */
      gqlRequest(
        request
      ).then(data => {
        /* Save the task's id in case it was just created */
        if (!task.id) {
          task.id = data.createTask.id;
        } 
      }).catch(e => {
        const errMsg = `Failed to save task: ${e}`;
        console.error(errMsg);
        showError(errMsg);
      });
    },

    /**
     * Delete a task.
     * @param task - task to delete as an object from the store.
     */
    deleteTask(task) {
      if (task.id !== NEW_TASK_ID) {
        /* Task must be also deleted from the server */
        gqlRequest(`mutation {
          deleteTask(id: "${task.id}") {
            id
          }
        }`).then(data => {
          console.info(`Deleted task '${task.title}' with id ${task.id}`);
          /* Also remove task from the store */
          removeTask(task);
        }).catch(e => {
          const errMsg = `Failed to delete task: ${e}`;
          console.error(errMsg);
          showError(errMsg);
        });
      } else {
        /* Just delete task from the store */
        removeTask(task);
      }


    },

    /**
     * Add a task to the current list.
     */
    addTask() {
      if (!this.currentList) {
        showModal("No list selected",
                  'Please select a specific list (not "All") before adding an item.');
        return;
      }

      store.tasks.push({
        id: NEW_TASK_ID,
        completed: false,
        title: "Enter task here",
        description: "",
        list: {
          id: this.currentList,
        }
      });

      /* wait a moment, then scroll list to the bottom */
      setTimeout(function() {
        document.getElementById("todo-container").scrollTo({
          top: 100000,
          behavior: "smooth"
        });
        /* select text in new item's title field */
        const titleInput = document.querySelector(`#task-${NEW_TASK_ID} .item-title`);
        titleInput.setSelectionRange(0, 1000);
        titleInput.focus();
      }, 100);
    },

    /**
     * Toggle completed state of a todo item.
     * @param task the todo item to toggle.
     */
    toggleCompleted(task) {
      task.completed = !task.completed;
    },

    /**
     * Return class object for a todo checked symbol
     *
     * @param task the item
     */
    todoCheckedClass(task) {
      return {
        "todo-checked": true,
        "completed": task.completed,
        "uncompleted": !task.completed,
      }
    },

    /**
     * Return class object for a todo item
     *
     * @param task the item
     */
    todoItemClass(task) {
      return {
        "list-item": true,
        "completed": task.completed,
      }
    },

  },

  computed: {

    /**
     * Add global store to the context, so we can refer to it in the template.
     */
    gStore() {
      return store;
    },

    /**
     * Return array of tasks to show.
     */
    filteredItems() {
      return store.tasks.filter((item) => {
        /* hide completed items if the option to show them is not set */
        if (!this.showCompleted && item.completed) {
          return false;
        }
        /* only return items of the current list */
        if (this.currentList && item.list.id !== this.currentList) {
          return false;
        }
        return true;
      })

    }

  },

}
</script>

<style lang="scss" scoped>

#todo-container {
  margin-top: 20px;
}

h1 {
  margin-bottom: 25px;
}

.btn-icon {
  width: 16px;
  height: 16px;
  cursor: pointer;
}

.todo-checked {
  width: 80px;
  height: 80px;
  cursor: pointer;
  margin-right: 20px;
  min-height: 80px;
  border-radius: 50%;
  border: 4px solid var(--bs-border-color);
  background-size: 80%;
  background-position: center center;
  background-repeat: no-repeat;
  &.uncompleted {
    &:hover {
      background-image: url(../assets/img/check-gray.svg);
    }
  }
  &.completed {
    border-color: #41ab57;
    background-image: url(../assets/img/check-green.svg);
  }
}

.header-buttons {
  float:right;
  font-size: 1rem;
}

.switch {
  padding-left: .5em;
  input {
    transform: scale(150%);
    margin-right: 6px;
  }
}

</style>
