<template>
  <div>
    <!-- Top bar -->
    <div v-if="isOwnCollection" class="flex flex-row flex-wrap gap-2 items-center mb-4">
      <button class="btn btn-blue" @click="show_modal_url = true">
        <fa-icon :icon="['fas', 'folder-open']" class="text-xl"></fa-icon> Load Wiki collection
      </button>
      <button class="btn btn-blue" @click="openInWiki()">
        <fa-icon :icon="['fas', 'external-link-alt']" class="text-xl"></fa-icon> Open in Wiki
      </button>
      <button class="btn btn-blue" @click="shareCollection()">
       <fa-icon :icon="['fas', 'share-alt']" class="text-xl"></fa-icon> Share
      </button>    
      <button class="btn btn-blue" @click="saveCollection()" :disabled="! modification">
        <fa-icon :icon="['fas', 'save']" class="text-xl"></fa-icon> Save changes
      </button>
      <button class="btn" :class="editRings ? 'btn-red' : 'btn-blue'" @click="editRings = ! editRings">
        <fa-icon :icon="['fas', 'ring']" class="text-xl"></fa-icon> Edit rings
      </button>
    </div>
    
    <!-- Data filters -->
    <div class="flex flex-row flex-wrap items-center gap-2 mb-4">
      <data-filter
        v-for="category in getFilters"
        :key="category.name"
        :category="category.name"
        :count="data_count[0][category.key].map((val, idx) => val + data_count[1][category.key][idx])"
        :data="data_model[category.key].data"
        :hasAll="category.hasAll"
      ></data-filter>

      <div class="flex flex-row flex-wrap items-center btn-group">
        <span class="mr-2">Show</span>
        <button class="btn btn-sm" :class="showCharacters ? 'btn-blue' : 'btn-white'" @click="setShowCharacters()">Characters</button>
        <button class="btn btn-sm" :class="showSummons ? 'btn-blue' : 'btn-white'" @click="setShowSummons()">Summons</button>
      </div>

      <checkbox v-model="showNames">Show names</checkbox>
      <checkbox v-model="showStars">Show stars</checkbox>
      <checkbox v-model="showAwakening">Show awakening</checkbox>
      <checkbox v-model="showRings">Show rings</checkbox>
    </div>

    <!-- Draw stats -->
    <div class="flex flex-col items-start mb-8">
      <a 
        class="btn-blue rounded-t font-bold hover:text-primary cursor-pointer p-2"
        :class="showStats ? '' : 'rounded-b'"
        @click="showStats = !showStats"
        title="Click to toggle..."
      >
        Collection statistics {{ filtersActive ? '(filters active)' : '' }}
        <fa-icon v-if=" ! showStats" :icon="['fas', 'angle-right']" class="ml-2"></fa-icon>
        <fa-icon v-else :icon="['fas', 'angle-down']" class="ml-2"></fa-icon>
      </a>
      <div class="flex flex-row flex-wrap p-2 bg-secondary" v-if="showStats">
        <div class="flex flex-col mx-4">
          <span class="mb-2">Characters <span class="tag text-inverse bg-inverse">{{ chara_count.sum }}/{{ chara_total.sum }}</span></span>
          <ul class="list-disc ml-4">
            <li class="mb-2">Gacha
              <ul>
                <li><label><input type="checkbox" v-model="chara_show[1000]"> Premium Draw</label>
                    <span class="tag bg-primary">{{ chara_count[1000] }}/{{ chara_total[1000] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[500]"> Classic Draw</label>
                    <span class="tag bg-primary">{{ chara_count[500] }}/{{ chara_total[500] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[600]"> Classic Draw II</label>
                    <span class="tag bg-primary">{{ chara_count[600] }}/{{ chara_total[600] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1010]"> Valentine</label>
                    <span class="tag bg-primary">{{ chara_count[1010] }}/{{ chara_total[1010] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1020]"> Holiday</label>
                    <span class="tag bg-primary">{{ chara_count[1020] }}/{{ chara_total[1020] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1030]"> Summer</label>
                    <span class="tag bg-primary">{{ chara_count[1030] }}/{{ chara_total[1030] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1040]"> Halloween</label>
                    <span class="tag bg-primary">{{ chara_count[1040] }}/{{ chara_total[1040] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1050]"> Zodiac</label>
                    <span class="tag bg-primary">{{ chara_count[1050] }}/{{ chara_total[1050] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1500]"> Flash Gala</label>
                    <span class="tag bg-primary">{{ chara_count[1500] }}/{{ chara_total[1500] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[1600]"> Premium Gala</label>
                    <span class="tag bg-primary">{{ chara_count[1600] }}/{{ chara_total[1600] }}</span></li>
              </ul>
            </li>
            <li class="mb-2">Non-gacha
              <ul>
                <li><label><input type="checkbox" v-model="chara_show[10]"> Eternals</label>
                    <span class="tag bg-primary">{{ chara_count[10] }}/{{ chara_total[10] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[20]"> Evokers</label>
                    <span class="tag bg-primary">{{ chara_count[20] }}/{{ chara_total[20] }}</span></li>
                <li><label><input type="checkbox" v-model="chara_show[null]"> Others</label>
                    <span class="tag bg-primary">{{ chara_count[null] }}/{{ chara_total[null] }}</span></li>
              </ul>
            </li>
          </ul>
        </div>
        <div class="flex flex-col mx-4">
          <span class="mb-2">Summons <span class="tag text-inverse bg-inverse">{{ summon_count.sum }}/{{ summon_total.sum }}</span></span>
          <ul class="list-disc ml-4">
            <li class="mb-2">Gacha
              <ul>
                <li><label><input type="checkbox" v-model="summon_show[1000]"> Premium Draw</label>
                    <span class="tag bg-primary">{{ summon_count[1000] }}/{{ summon_total[1000] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[500]"> Classic Draw</label>
                    <span class="tag bg-primary">{{ summon_count[500] }}/{{ summon_total[500] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[600]"> Classic Draw II</label>
                    <span class="tag bg-primary">{{ summon_count[600] }}/{{ summon_total[600] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[1020]"> Holiday</label>
                    <span class="tag bg-primary">{{ summon_count[1020] }}/{{ summon_total[1020] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[1030]"> Summer</label>
                    <span class="tag bg-primary">{{ summon_count[1030] }}/{{ summon_total[1030] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[1600]"> Non-ticketable</label>
                    <span class="tag bg-primary">{{ summon_count[1600] }}/{{ summon_total[1600] }}</span></li>
              </ul>
            </li>
            <li class="mb-2">Non-gacha
              <ul>
                <li><label><input type="checkbox" v-model="summon_show[20]"> Arcarum</label>
                    <span class="tag bg-primary">{{ summon_count[20] }}/{{ summon_total[20] }}</span></li>
                <li><label><input type="checkbox" v-model="summon_show[null]"> Others</label>
                    <span class="tag bg-primary">{{ summon_count[null] }}/{{ summon_total[null] }}</span></li>
              </ul>
            </li>
          </ul>
        </div>
      </div>
    </div>

    <!-- Ring edit warning -->
    <div v-if="editRings" class="sticky top-0 bg-tertiary shadow-md z-10 mb-4 flex flex-row justify-between items-center">
      <span></span>
      <h2>
        <fa-icon :icon="['fas', 'ring']" class="text-xl text-red-400"></fa-icon>
        Editing Purity rings
        <fa-icon :icon="['fas', 'ring']" class="text-xl text-red-400"></fa-icon>
      </h2>
      <button class="btn btn-red" @click="editRings = false">
        Stop editing
      </button>
    </div>

    <!-- Collection -->
    <div v-if="loading === true">
      Loading...
    </div>
    <div v-else>
      <div v-for="i in 7" :key="i" :class="getUnits[0][i-1].length > 0 || getUnits[1][i-1].length > 0 ? 'mb-4' : ''">
        <div class="flex flex-row flex-wrap" v-if="showCharacters">
          <span class="flex flex-col" style="width: 105px;" v-for="chara in getUnits[0][i-1]" :key="chara.id">
            <a
              class="text-xs text-primary h-5 px-1 text-center truncate"
              target="_blank"
              :href="'https://gbf.wiki/' + chara.n"
              :title="getName(chara)"
              v-if="showNames"
            >{{ getName(chara) }}</a>
            <span class="relative">
              <img
                :class="chara.owned ? '' : 'grayscale-80'"
                style="height: 60px;"
                :title="getName(chara)"
                :src="'/img/unit_small/' + chara.id + '000.jpg'"
                @click="selectChara(chara)"
              >
              <img
                v-if="showRings && chara.ring"
                class="absolute bottom-0 right-0 pointer-events-none"
                src="/img/icon_pring.png"
                title="Perpetuity Ring"
              >
            </span>
            <span @click="starsModified()" style="min-height: 21px;" v-if="showStars">
              <stars-line
                v-if="chara.owned"
                :base="chara.sb"
                :extra="chara.sm"
                :current.sync="chara.sc"
                :max="5"
                :readOnly=" ! isOwnCollection"
                :transcendance="true"
              ></stars-line>
            </span>
            <span @click="starsModified()" v-if="showAwakening && chara.owned" class="text-sm pb-2 pl-1">
              <stat-input
                shortName="Awake"
                longName="Awakening"
                :class="chara.aw == MAX_AWAKENING ? 'text-link-primary' : ''"
                :prop.sync="chara.aw"
                :length="1"
                :max="MAX_AWAKENING"
              ></stat-input>
              <fa-icon
                v-if="chara.aw < MAX_AWAKENING"
                @click="chara.aw = MAX_AWAKENING"
                :icon="['fas', 'check']"
                class="ml-1 cursor-pointer"
                title="Maximize awakening"
              ></fa-icon>
            </span>
          </span>
        </div>
        <div class="flex flex-row flex-wrap" v-if="showSummons">
          <span class="flex flex-col" style="width: 105px;" v-for="summon in getUnits[1][i-1]" :key="summon.id">
            <a
              class="text-xs text-primary h-5 px-1 text-center truncate"
              target="_blank"
              :href="'https://gbf.wiki/' + summon.n"
              :title="getName(summon)"
              v-if="showNames"
            >{{ getName(summon) }}</a>
            <img
              :class="summon.owned ? '' : 'grayscale-80'"
              style="height: 60px;"
              :title="getName(summon)"
              :src="'/img/unit_small/' + summon.id + '000.jpg'"
              @click="selectSummon(summon)"
            >
            <span @click="starsModified()" style="min-height: 21px;" v-if="showStars">
              <stars-line
                v-if="summon.owned"
                :base="summon.sb"
                :extra="summon.sm"
                :current.sync="summon.sc"
                :max="5"
                :readOnly=" ! isOwnCollection"
                :transcendance="true"
              ></stars-line>
            </span>
          </span>
        </div>
      </div>
    </div>

    <!-- For clipboard support -->
    <input v-show="clipboard_text.length > 0" id="clipboardInput" readonly type="text" :value="clipboard_text">

    <!-- Modal -->
    <modal-url v-model="show_modal_url" @import="loadWikiCollection"></modal-url>
  </div>
</template>

<script>
import { mapState } from 'vuex'

import base64js from '@/js/libs/base64js.js'
import Utils from '@/js/utils.js'
import DataModel from '@/js/data-model.js'
import { LANGUAGES } from '@/js/lang'
import collectionStoreMixin from '@/store/modules/collection-tracker'

import Checkbox from '@/components/common/Checkbox.vue'
import StatInput from '@/components/common/StatInput.vue'
import DataFilter from '@/components/common/DataFilter.vue'
import ModalUrl from '@/components/ModalWikiURL.vue'
import StarsLine from '@/components/StarsLine.vue'

const lsMgt = new Utils.LocalStorageMgt('CollectionTracker');

const categories = [
  {
    name: "Name",
    isColumn: true,
    isFilter: false,
    hasAll: true,
    key: "n",
  },
  {
    name: "Rarity",
    isColumn: false,
    isFilter: true,
    hasAll: true,
    key: "ri",
  },
  {
    name: "Element",
    isColumn: true,
    isFilter: true,
    hasAll: true,
    key: "e",
  },
  {
    name: "Type",
    isColumn: true,
    isFilter: true,
    hasAll: true,
    key: "t",
  },
  {
    name: "Race",
    isColumn: true,
    isFilter: true,
    hasAll: true,
    key: "ra",        
  },
  {
    name: "Weapon",
    isColumn: true,
    isFilter: true,
    hasAll: true,
    key: "w",
  },
  {
    name: "Owned",
    isColumn: false,
    isFilter: true,
    hasAll: false,
    key: "owned",
  },
  {
    name: "Ringed",
    isColumn: false,
    isFilter: true,
    hasAll: false,
    key: "ring",
  }
];

function getDataModel() {
  // Copy the data model locally to modify "checked" properties
  return Object.fromEntries(categories.map(c => [c.key, Utils.copy(DataModel[c.key])]));
}

function getDataCount() {
  return Object.fromEntries(categories.map(c => {
    if (DataModel[c.key].data) {
      return [c.key, DataModel[c.key].data.map(d => 0)];
    }
    return [c.key, []];
  }));
}

const INITIAL_DATA = () => {
  return {
    // Add the corresponding values in the store (collection-tracker.js)
    chara_show: {
      null: true, 10: true, 20: true, 500: true, 600: true,
      1000: true, 1010: true, 1020: true, 1030: true, 1040: true, 1050: true,
      1500: true, 1600: true,
    },
    summon_show: {
      null: true, 20: true, 500: true, 600: true,
      1000: true, 1020: true, 1030: true,
      1600: true,
    },
    data_model: getDataModel(),
    // 0: characters, 1: summons
    data_count: [getDataCount(), getDataCount()],
    modification: false,
    showNames: true,
    showStars: true,
    showAwakening: false,
    showRings: true,
    showCharacters: true,
    showSummons: true,
    showStats: false,
    show_modal_url: false,
    clipboard_text: '',
    loading: true,
    editRings: false,
  }
};

export default {
  components: {
    Checkbox,
    StatInput,
    DataFilter,
    ModalUrl,
    StarsLine,
  },
  mixins: [
    collectionStoreMixin
  ],
  head: {
    title: 'Granblue.Party - Collection Tracker',
    desc: 'Track the characters and summons you unlocked, and share your collection with your friends',
    image: 'https://www.granblue.party/img/card_collection.jpg',
    keywords: 'collection, tracker, characters, summons, share'
  },
  data() {
    return INITIAL_DATA();
  },
  methods: {
    getName(element) {
      if (this.isLangEnglish) {
        return element.n;
      }
      return element.nj;
    },
    setShowCharacters() {
      this.showCharacters = ! this.showCharacters;
      lsMgt.setValue('showCharacters', this);
    },
    setShowSummons() {
      this.showSummons = ! this.showSummons;
      lsMgt.setValue('showSummons', this);
    },
    selectChara(object) {
      if (this.isOwnCollection) {
        if (this.editRings) {
          object.ring = ! object.ring;
        }
        else {
          object.owned = ! object.owned;
          if (object.owned) {
            this.chara_count.sum++;
            this.chara_count[object.d]++;
          }
          else {
            this.chara_count.sum--;
            this.chara_count[object.d]--;
          }
        }

        this.modification = true;
      }
    },
    selectSummon(object) {
      if (this.isOwnCollection) {
        if (this.editRings) {
          return;
        }

        object.owned = ! object.owned;
        if (object.owned) {
          this.summon_count.sum++;
          this.summon_count[object.d]++;
        }
        else {
          this.summon_count.sum--;
          this.summon_count[object.d]--;
        }
        this.modification = true;
      }
    },
    starsModified() {
      if (this.isOwnCollection) {
        this.modification = true;
      }
    },
    saveCollection() {
      if (this.isOwnCollection) {
        const postData = {c: [], s: []};
        this.characters.forEach(cat => {
          cat.forEach(chara => {
            if (chara.owned != null) {
              postData.c.push([chara.id, chara.sc, chara.owned, chara.aw, chara.ring]);
            }
          });
        });
        this.summons.forEach(cat => {
          cat.forEach(summ => {
            if (summ.owned != null) {
              postData.s.push([summ.id, summ.sc, summ.owned]);
            }
          });
        });

        this.axios.post('/tracker/save', postData)
          .then(response => this.$store.dispatch('addMessage', {message: 'Collection saved successfully'}))
          .catch(error => this.$store.dispatch('addAxiosErrorMessage', error))
      }
    },
    openInWiki() {
      let strings = {
        'c': ["","",""], // [R, SR, SSR]
        's': ["","",""],
      };
      let selected = {
        'c': [{},{},{}],
        's': [{},{},{}],
      };

      this.characters.flat().forEach(unit => {
        if (unit.owned === true) {
          const unit_id = unit.id.toString();
          const short_id = unit_id.slice(2, 3) + unit_id.slice(4);
          if (short_id.length === 4) {
            const rarity = unit.ri;
            const index = parseInt(short_id.slice(1), 10);
            // Wiki evo count doesn't go higher than 6 for transcendance
            selected.c[rarity][index] = parseInt(Math.min(unit.sc, 6), 10) + 1;
          }
        }
      });
      this.summons.flat().forEach(unit => {
        if (unit.owned === true) {
          const unit_id = unit.id.toString();
          const short_id = unit_id.slice(2, 3) + unit_id.slice(4);
          if (short_id.length === 4) {
            const rarity = unit.ri;
            const index = parseInt(short_id.slice(1), 10);
            // Wiki evo count doesn't go higher than 6 for transcendance
            selected.s[rarity][index] = parseInt(unit.sc, 10) + 1;
          }
        }
      });

      // convert to a bit array
      ['c', 's'].forEach(type => {
        [0, 1, 2].forEach(rarity => {
          let high_id = 0;
          const obj = selected[type][rarity];
          for (let index in obj)
            high_id = Math.max(high_id, index);

          // Group 8 items with 3 bits each
          const parts = Math.floor(high_id / 8) + 1;
          const size = parts * 3;
          let buffer = new Uint8Array(size);

          for (let i = 0; i <= Math.floor(high_id / 8); i++) {
            let evos = 0x000000;
            for (let j = 0; j < 8; j++) {
              let evo = obj[i*8+j];
              if (evo == undefined)
                evo = 0;
              evos |= (evo << (j*3));
            }
            buffer[i*3]   = (evos >>  0) & 0xFF;
            buffer[i*3+1] = (evos >>  8) & 0xFF;
            buffer[i*3+2] = (evos >> 16) & 0xFF;
          }
          const base64 = base64js.fromByteArray(buffer)
          if (base64 != 'AAAA') {
            strings[type][rarity] += base64;
          }
        });
      });

      const wiki_url = "https://gbf.wiki/Collection_Tracker#o3." + strings.c[2] + "." + strings.c[1] + "." + strings.c[0]
        + "." + strings.s[2] + "." + strings.s[1] + "." + strings.s[0];
      window.open(wiki_url);
    },
    shareCollection() {
      const text = window.location.href  + '/' + this.$store.getters.getUserId;
      // Put in clipboard
      this.clipboard_text = text;
      let self = this;
      this.$nextTick().then(() => {
        const input = document.getElementById("clipboardInput");
        input.select();
        document.execCommand("copy");
        self.clipboard_text = '';

        self.$store.dispatch('addMessage', {message: 'URL copied to clipboard'})
      });
    },
    loadCollection() {
      let userId = "";
      if (this.isOwnCollection) {
        userId = this.$store.getters.getUserId;
      }
      else {
        // Defined when viewing other collections
        userId = this.$route.params.collection_id;
      }

      return this.$store.dispatch('collection/fetchCollection', userId);
    },
    loadWikiCollection(url) {
      let units = new Map();

      let url_parts = url.split('#');
      if (url_parts.length == 1) {
        url_parts = url_parts[0];
      }
      else {
        url_parts = url_parts[1];
      }

      let parts = url_parts.split('.');
      for (let i = 1; i <= 7; i++) {
        if (typeof parts[i] !== 'string') {
          parts[i] = '';
        }
      }
      const strings = { 
        3020000: parts[3], 3030000: parts[2], 3040000: parts[1],
        2020000: parts[6], 2030000: parts[5], 2040000: parts[4]
      };

      // Is URL valid ?
      if (parts[1].length + parts[2].length + parts[3].length + parts[4].length + parts[5].length + parts[6].length < 1) {
        this.$store.dispatch('addMessage', {title: 'Error', message: 'Invalid wiki collection URL'});
        return;
      }

      for (let [key, value] of Object.entries(strings)) {
        if(value.length < 1)
          continue;
        
        let buffer = base64js.toByteArray(value);
        let len = buffer.length / 3;
        for (let i = 0; i < len; i++) {
          let evos = 0;
          evos |= (buffer[i*3  ] <<  0);
          evos |= (buffer[i*3+1] <<  8);
          evos |= (buffer[i*3+2] << 16);

          for (let j = 0; j < 8; j++) {
            let evo = ((evos >> (j*3)) & 0x07) - 1;
            if (evo < 0)
              continue;
            let short_id = parseInt(key, 10) + (i*8+j);
            units.set(short_id, evo);
          }
        }
      }

      this.characters.flat().forEach(c => {
        const stars = units.get(c.id);
        if (stars !== undefined) {
          c.owned = true;
          c.sc = stars;
        }
        else if (c.owned === true) {
          c.owned = false;
        }
      });
      this.summons.flat().forEach(c => {
        const stars = units.get(c.id);
        if (stars !== undefined) {
          c.owned = true;
          c.sc = stars;
        }
        else if (c.owned === true) {
          c.owned = false;
        }
      });

      this.modification = true;
    },
  },
  computed: {
    ...mapState('collection', [
      'characters',
      'chara_count',
      'chara_total',
      'summons',
      'summon_count',
      'summon_total'
    ]),
    MAX_AWAKENING() {
      return 9;
    },
    getFilters() {
      return categories.filter(c => { return c.isFilter });
    },
    filtersActive() {
      return Object.values(this.chara_show).some(c => !c) || Object.values(this.summon_show).some(c => !c)
    },
    isOwnCollection() {
      return this.$route.params.collection_id === undefined;
    },
    isLangEnglish() {
      return this.$store.getters.getLang === LANGUAGES.EN;
    },
    getCharacters() {
      if (this.characters) {
        const newDataCount = getDataCount();
        const characters = this.characters.map(element =>
          element.filter(chara => {
            if ( ! this.chara_show.hasOwnProperty(chara.d)) {
              console.log('Unknown Character category ' + chara.d + '. Please report this error to the administrator.');
              return true;
            }
            if ( ! this.chara_show[chara.d]) {
              return false;
            }
            const show = this.getFilters.every(e => {
              return this.data_model[e.key].show(chara[e.key])
            });
            // Increment filter counts
            if (show && this.showCharacters) {
              this.getFilters.forEach(e => {
                this.data_model[e.key].add(chara[e.key], newDataCount[e.key]);
              });
            }
            return show;
          })
        );
        this.$set(this.data_count, 0, newDataCount);
        return characters;
      }
      return [[],[],[],[],[],[],[]];
    },
    getSummons() {
      if (this.summons) {
        const newDataCount = getDataCount();
        const summons = this.summons.map(element =>
          element.filter(summ => {
            const show = this.getFilters.every(e => {
              // Summons have less filters than characters
              if (summ[e.key] === undefined) {
                return true;
              }
              if ( ! this.summon_show.hasOwnProperty(summ.d)) {
                console.log('Unknown Summon category ' + summ.d + '. Please report this error to the administrator.');
                return true;
              }
              if ( ! this.summon_show[summ.d]) {
                return false;
              }
              return this.data_model[e.key].show(summ[e.key]);
            });

            if (show && this.showSummons) {
              this.getFilters.forEach(e => {
                if (summ[e.key] !== undefined) {
                  this.data_model[e.key].add(summ[e.key], newDataCount[e.key]);
                }                
              });
            }
            return show;
          })
        );
        this.$set(this.data_count, 1, newDataCount);
        return summons;
      }
      return [[],[],[],[],[],[],[]];
    },
    getUnits() {
      return [
        this.getCharacters,
        this.getSummons
      ];
    }
  },
  serverPrefetch() {
    return this.loadCollection();
  },
  async mounted() {
    lsMgt.getValue(this, 'showNames');
    lsMgt.getValue(this, 'showStars');
    lsMgt.getValue(this, 'showAwakening');
    lsMgt.getValue(this, 'showRings');
    lsMgt.getValue(this, 'showCharacters');
    lsMgt.getValue(this, 'showSummons');

    const chara_show = lsMgt.fetchValue('chara_show');
    if (chara_show !== undefined) {
      for (const [key, value] of Object.entries(chara_show)) {
        if (this.chara_show.hasOwnProperty(key)) {
          this.chara_show[key] = value;
        }
      }
    }
    const summon_show = lsMgt.fetchValue('summon_show');
    if (summon_show !== undefined) {
      for (const [key, value] of Object.entries(summon_show)) {
        if (this.summon_show.hasOwnProperty(key)) {
          this.summon_show[key] = value;
        }
      }
    }

    [0, 1].forEach(index => {
      const owned = lsMgt.fetchValue('owned-' + index);
      if (owned !== undefined) {
        this.$set(this.data_model.owned.data[index], 'checked', owned);
      }
      const ring = lsMgt.fetchValue('ring-' + index);
      if (ring !== undefined) {
        this.$set(this.data_model.ring.data[index], 'checked', ring);
      }
    });

    await this.loadCollection()
      .then(_ => this.loading = false);
  },
  watch: {
    '$store.getters.getUserId'(id) {
      if (id === null) {
        this.$router.push({name: "collection401"}).catch(() => {});
      }
      else {
        Object.assign(this.$data, INITIAL_DATA());
        this.loadCollection()
          .then(_ => this.loading = false);
      }
    },
    '$route'(to, from) {      
      // When the route changes from "Other collection" to "My collection"
      Object.assign(this.$data, INITIAL_DATA());
      this.loadCollection()
        .then(_ => this.loading = false);
    },
    chara_show: {
      handler() {
        lsMgt.setValue('chara_show', this);
      },
      deep: true
    },
    summon_show: {
      handler() {
        lsMgt.setValue('summon_show', this);
      },
      deep: true
    },
    'data_model.owned.data': {
      handler() {
        lsMgt.setNamedValue('owned-0', this.data_model.owned.data[0].checked);
        lsMgt.setNamedValue('owned-1', this.data_model.owned.data[1].checked);
      },
      deep: true
    },
    'data_model.ring.data': {
      handler() {
        lsMgt.setNamedValue('ring-0', this.data_model.ring.data[0].checked);
        lsMgt.setNamedValue('ring-1', this.data_model.ring.data[1].checked);
      },
      deep: true
    },
    showNames() {
      lsMgt.setValue('showNames', this);
    },
    showStars() {
      lsMgt.setValue('showStars', this);
    },
    showAwakening() {
      lsMgt.setValue('showAwakening', this);
    },
    showRings() {
      lsMgt.setValue('showRings', this);
    }
  }
}
</script>