<template>
  <div class="work">
    <div class="overflow-x-wrapper">
      <table>
        <tr>
          <td>ID</td>
          <td>{{ id }}<button class="copy-btn" @click="copy(id)">Copy</button></td>
        </tr>
        <tr v-for="(value, key, index) in work" :key="index">
          <td>{{ properties[key] }}</td>
          <td>
            <template v-if="!edit">
              {{ workEdit[key] || value }}
            </template>
            <input
            v-else
            :type="typeof value === 'number' ? 'number' : 'text'"
            :value="workEdit[key] || value"
            @input="addToEdited(key, $event.target.value)">
            <button class="copy-btn" @click="copy(value)" v-show="!edit">Copy</button>
          </td>
        </tr>
        <tr>
          <td>Materiāli</td>
          <td v-if="materials.length > 0">
            <div v-for="item in workMaterials" :key="item.id">
              <router-link :to="{ name: 'Material', params: { id: item.id } }">
                {{ item.name }}
              </router-link>
              <button
              class="btn-round-small btn-red hover-3"
              style="margin-left: 4px;"
              @click="removeMaterial(item.id)">
                &#x00D7;
              </button>
            </div>
            <button
            class="btn-round-small btn-blue"
            v-show="!workMaterials || workMaterials.length < materials.length"
            @click="showMaterialMenu">
              +
            </button>
            <div class="material-menu" :style="materialMenuStyle" ref="materialMenu" @blur="materialMenuStyle.display = 'none'" tabindex="0">
              <input type="text" v-model.trim="materialMenuSearch" placeholder="Nosaukums..." ref="materialMenuSearch" @blur="materialMenuStyle.display = 'none'">
              <ul>
                <li v-for="item in filteredMenuMaterials" @click="updateWithMaterial(item)" :key="item.id">
                  {{ item.name }} <span class="amount">({{ item.amount }})</span>
                </li>
              </ul>
            </div>
          </td>
          <td v-else>
            null
          </td>
        </tr>
        <tr>
          <td>Mehānismi</td>
          <td v-if="mechanisms.length > 0">
            <div v-for="item in workMechanisms" :key="item.id">
              <router-link :to="{ name: 'Mechanism', params: { id: item.id } }">
                {{ item.name }}
              </router-link>
              <button
              class="btn-round-small btn-red hover-3"
              style="margin-left: 4px;"
              @click="removeMechanism(item.id)">
                &#x00D7;
              </button>
            </div>
            <button
            class="btn-round-small btn-blue"
            v-show="!workMechanisms || workMechanisms.length < mechanisms.length"
            @click="showMechanismMenu">
              +
            </button>
            <div class="material-menu" :style="mechanismMenuStyle" ref="mechanismMenu" @blur="mechanismMenuStyle.display = 'none'" tabindex="0">
              <input type="text" v-model.trim="mechanismMenuSearch" placeholder="Nosaukums..." ref="mechanismMenuSearch" @blur="mechanismMenuStyle.display = 'none'">
              <ul>
                <li v-for="item in filteredMenuMechanisms" @click="updateWithMechanism(item)" :key="item.id">
                  {{ item.name }} <span class="amount">({{ item.amount }})</span>
                </li>
              </ul>
            </div>
          </td>
          <td v-else>
            null
          </td>
        </tr>
        <tr v-for="(value, key, index) in uneditable" :key="index + Math.random()">
          <td>{{ properties[key] }}</td>
          <td>
            {{ value }}
            <button class="copy-btn" @click="copy(value)">Copy</button>
          </td>
        </tr>
      </table>
    </div>
    <button
    class="btn btn-green border"
    v-show="!edit"
    @click="edit = true">
      Labot
    </button>
    <button
    class="btn btn-green border"
    v-show="edit"
    @click="updateWork">
      Saglabāt
    </button>
    <button
    class="btn btn-yellow border"
    style="margin-left: 5px;"
    v-show="edit"
    @click="workEdit = {}; edit = false">
      Atcelt
    </button>
    <button
    class="btn btn-red border"
    style="margin-top: 10px; margin-left: 5px;"
    @click="deleteWork">
      Dzēst
    </button>
  </div>
</template>

<script>
import { API } from 'aws-amplify';
import { getWork, listUserMaterials, listUserMechanisms } from "../graphql/queries";
import { updateWork, deleteWork } from "../graphql/mutations";

export default {
  created() {
    this.getWork();
    this.listUserMaterials();
    this.listUserMechanisms();
  },
  data() {
    return {
      id: this.$route.params.id,
      work: {},
      uneditable: {},
      workEdit: {},
      edit: false,
      workMaterials: [],
      materials: [],
      materialMenuStyle: {
        display: "none",
      },
      menuMaterials: [],
      materialMenuSearch: '',
      workMechanisms: [],
      mechanisms: [],
      mechanismMenuStyle: {
        display: "none",
      },
      menuMechanisms: [],
      mechanismMenuSearch: '',
      properties: {
        name: 'Nosaukums',
        id: 'ID',
        createdAt: 'Izveidošanas datums',
        updatedAt: 'Atjaunošanas datums',
        unit_of_measurement: 'Mērvienība',
        owner: 'Lietotājs',
        amount: 'Daudzums',
        code: 'Kods',
        time_norm: 'Laika norma (c/h)',
        pay_rate: 'Darba samaksas likme (EUR/h)',
        materials: 'Materiāli',
        mechanisms: 'Mehānismi'
      },
    };
  },
  computed: {
    materialIds() {
      return this.workMaterials.map(x => x.id);
    },
    mechanismIds() {
      return this.workMechanisms.map(x => x.id);
    },
    filteredMenuMaterials() {
      return this.menuMaterials.filter(x => x.name.toLowerCase().includes(this.materialMenuSearch.toString().toLowerCase()));
    },
    filteredMenuMechanisms() {
      return this.menuMechanisms.filter(x => x.name.toLowerCase().includes(this.mechanismMenuSearch.toString().toLowerCase()));
    }
  },
  methods: {
    async getWork() {
      const work = await API.graphql({
        query: getWork,
        variables: { id: this.id }
      });
      let result = work.data.getWork;
      if (!result) {
        this.$router.push({ name: 'NotFound' });
      } else {
        if (result.materials) this.workMaterials = result.materials;
        if (result.mechanisms) this.workMechanisms = result.mechanisms;
        this.uneditable.owner = result.owner;
        this.uneditable.createdAt = result.createdAt;
        this.uneditable.updatedAt = result.updatedAt;
        const removable = ['id', 'materials', 'mechanisms', 'owner', 'createdAt', 'updatedAt'];
        removable.forEach(x => delete result[x]);
        this.work = result;
      }
    },
    async updateWork() {
      const input = {id: this.id};
      for (const [key, value] of Object.entries(this.workEdit)) {
        input[key] = value;
        this.work[key] = value;
      }
      await API.graphql({
        query: updateWork,
        variables: { input }
      });
      this.workEdit = {};
      this.edit = false;
    },
    async deleteWork() {
      API.graphql({
        query: deleteWork,
        variables: { input: {id: this.id} }
      }).then(() => this.$router.push({ name: 'Works' }));
    },
    async listUserMaterials() {
      const materials = await API.graphql({
        query: listUserMaterials,
      });
      this.materials = materials.data.listUserMaterials.items;
    },
    async removeMaterial(id) {
      const index = this.materialIds.findIndex(i => i === id);
      if (index !== -1) {
        this.workMaterials.splice(index, 1);
        await API.graphql({
          query: updateWork,
          variables: { input: {id: this.id, materials: this.materialIds.length === 0 ? null : this.materialIds} }
        });
      }
    },
    async listUserMechanisms() {
      const mechanisms = await API.graphql({
        query: listUserMechanisms,
      });
      this.mechanisms = mechanisms.data.listUserMechanisms.items;
    },
    async removeMechanism(id) {
      const index = this.mechanismIds.findIndex(i => i === id);
      if (index !== -1) {
        this.workMechanisms.splice(index, 1);
        await API.graphql({
          query: updateWork,
          variables: { input: {id: this.id, mechanisms: this.mechanismIds.length === 0 ? null : this.mechanismIds} }
        });
      }
    },
    addToEdited(key, value) {
      if (this.work[key] === value && this.workEdit[key]) {
        delete this.workEdit[key];
      } else {
        this.workEdit[key] = value;
      }
    },
    showMaterialMenu() {
      if (this.materialIds.length === 0) {
        this.menuMaterials = this.materials;
      } else {
        this.menuMaterials = this.materials.filter(x => !this.materialIds.includes(x.id));
      }
      this.materialMenuStyle.display = 'block';
      this.$nextTick(() => {
        this.$refs.materialMenuSearch.focus();
      });
    },
    async updateWithMaterial(item) {
      API.graphql({
        query: updateWork,
        variables: { input: {id: this.id, materials: [...this.materialIds, item.id]} }
      });
      this.workMaterials.push(item);
      this.materialMenuSearch = '';
      this.$refs.materialMenu.blur();
    },
    showMechanismMenu() {
      if (this.mechanismIds.length === 0) {
        this.menuMechanisms = this.mechanisms;
      } else {
        this.menuMechanisms = this.mechanisms.filter(x => !this.mechanismIds.includes(x.id));
      }
      this.mechanismMenuStyle.display = 'block';
      this.$nextTick(() => {
        this.$refs.mechanismMenuSearch.focus();
      });
    },
    async updateWithMechanism(item) {
      API.graphql({
        query: updateWork,
        variables: { input: {id: this.id, mechanisms: [...this.mechanismIds, item.id]} }
      });
      this.workMechanisms.push(item);
      this.mechanismMenuSearch = '';
      this.$refs.mechanismMenu.blur();
    },
    copy(text) {
      navigator.clipboard.writeText(text).catch(error => {
        console.error(error);
      });
    }
  }
}
</script>

<style scoped>
button:disabled,
button[disabled] {
  opacity: 0.5;
  cursor: default;
}

input:disabled[type="text"],
input[disabled][type="text"] {
  background: none;
  box-shadow: none;
  border-color: transparent;
}

.material-menu {
  z-index: 99999;
  position: absolute;
  background: #fff;
  border: 1px solid #afafaf;
  border-radius: 5px;
  box-shadow: 0px 0px 5px rgb(0 0 0 / 0.3);
  font-size: 14px;
  font-weight: bold;
  left: 50%;
  transform: translate(-50%, 0);
  -webkit-transform: translate(-50%, 0);
  -ms-transform: translate(-50%, 0);
  width: fit-content;
  text-align: left;
}

.material-menu:focus {
  outline: none;
}

.material-menu ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

.material-menu li {
  padding: 7px;
  cursor: pointer;
}

.material-menu li:hover {
  background: #d6ebf3;
}

.material-menu input, .mechanism-menu input {
  width: calc(100% - 20px);
  padding: 4px;
  margin: 4px;
}

.material-menu:focus, .material-menu:focus-within,
.mechanism-menu:focus, .mechanism-menu:focus-within {
  display: block !important;
  outline: none;
}

.small-text {
  font-size: 11px;
  font-weight: normal;
}

td input[type="text"]:not(.material-menu input, .mechanism-menu input) {
  text-align: center;
  font-size: inherit;
  max-width: none;
  border-radius: 5px;
  border: 1px solid #8c8c8c;
  padding: 3px;
  box-shadow: inset 0px 0px 5px #d7dcda;
}

td input[type="number"] {
  text-align: center;
  font-size: inherit;
  max-width: 75px;
  border-radius: 5px;
  border: 1px solid #8c8c8c;
  padding: 3px;
  box-shadow: inset 0px 0px 5px #d7dcda;
}

.overflow-x-wrapper {
  overflow-x: auto;
  margin: 10px 5px;
}

.amount {
  color: #7fb5ca;
}
</style>