<template>
  <div>
    <div class="preset-select">
      <SelectComponent
        :options="getPresetOptions()"
        :onChange="(v) => loadPreset(v)"
        :placeholder="getPresetPlaceholder()"
        :key="generation"
      />
    </div>
    <div v-for="category in codeCategories" v-bind:key="category.identifier" class="code-group">
      <div class="category-title">{{ getCategoryTitle(category) }}</div>
      <ul>
        <li
          v-for="(code, idx) in availableCodes.filter((c) => c.category === category.identifier)"
          v-bind:key="idx"
          :class="code.selected ? 'checked' : code.disabled ? 'disabled' : ''"
          @click="toggle(code)"
          @mouseover="inspect(code)"
        >
          {{ getCodeTitle(code) }}
        </li>
        <li
          v-if="category.identifier === 'loader'"
          :class="stageLoaderSelected ? 'checked' : ''"
          @click="toggleStageLoader()"
          @mouseover="showStageLoaderHelp()"
        >
          {{ getStageLoaderLabel() }}
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import { translateCode, translate } from '../i18n/localeHelper';
import codeCategories from '../data/codeCategories.json';
import presetCategories from '../data/presetCategories.json';

export default {
  props: {
    codes: { type: Array },
    onSelectionChanged: { type: Function },
    onInspect: { type: Function },
    onStageLoaderToggle: { type: Function },
    onInspectStageLoader: { type: Function },
  },
  mounted() {
    this.populate();
  },
  watch: {
    codes: function () {
      this.populate();
      this.unselectStageLoader();
    },
  },
  data() {
    return {
      availableCodes: [],
      codeCategories,
      presetCategories,
      stageLoaderSelected: false,
      generation: 0,
    };
  },
  methods: {
    getPresetOptions() {
      return presetCategories.map((c) => ({
        label: c.i18nKey,
        value: c.identifier,
      }));
    },
    loadPreset(identifier) {
      if (
        (this.stageLoaderSelected || this.availableCodes.find((c) => c.selected)) &&
        !confirm(translate('common.selectionreset', this.$lang))
      ) {
        this.generation++;
        return;
      }

      for (const code of this.availableCodes) {
        code.selected = code.presets.includes(identifier);
      }

      this.unselectStageLoader();
      this.refreshDisabledCodes();
      this.onSelectionChanged(this.availableCodes.filter((c) => c.selected));
      this.generation++;
    },
    getPresetPlaceholder() {
      return translate('common.loadpresetplaceholder', this.$lang);
    },
    unselectStageLoader() {
      if (this.stageLoaderSelected) {
        this.stageLoaderSelected = false;
        this.onStageLoaderToggle(false);
      }
    },
    getCodeTitle(code) {
      return translateCode(code, this.$lang).title;
    },
    getCategoryTitle(category) {
      return translate(category.i18nKey, this.$lang);
    },
    getStageLoaderLabel() {
      return translate('headers.stageloader', this.$lang);
    },
    toggleStageLoader() {
      for (const c of this.availableCodes.filter((c) => c.category === 'loader' && c.selected)) {
        c.selected = false;
      }

      const newState = !this.stageLoaderSelected;
      this.stageLoaderSelected = newState;
      this.onStageLoaderToggle(newState);
      this.refreshDisabledCodes();
      this.onSelectionChanged(this.availableCodes.filter((c) => c.selected));
    },
    refreshDisabledCodes() {
      for (const code of this.availableCodes) {
        if (code.dependsOn) {
          if (code.dependsOn === 'loader' && this.stageLoaderSelected) {
            code.disabled = false;
          } else if (
            !this.availableCodes.some((c) => c.selected && c.category === code.dependsOn)
          ) {
            code.disabled = true;
            code.selected = false;
          } else {
            code.disabled = false;
          }
        }
      }
    },
    toggle(code) {
      if (!code.selected && codeCategories.find((c) => c.identifier === code.category).exclusive) {
        for (const availableCode of this.availableCodes.filter(
          (c) => c.category === code.category && c.selected,
        )) {
          availableCode.selected = false;
        }
      }

      if (!code.selected && code.category === 'loader' && this.stageLoaderSelected) {
        this.stageLoaderSelected = false;
        this.onStageLoaderToggle(false);
      }

      code.selected = code.disabled ? false : !code.selected;
      this.refreshDisabledCodes();
      this.onSelectionChanged(this.availableCodes.filter((c) => c.selected));
    },
    populate() {
      this.availableCodes = this.codes.map((c) => ({ ...c, selected: false }));
      this.refreshDisabledCodes();
    },
    inspect(code) {
      this.onInspect(code);
    },
    showStageLoaderHelp() {
      this.onInspectStageLoader();
    },
  },
};
</script>

<style scoped>
.category-title {
  color: white;
  font-weight: 500;
  text-align: center;
  background: #383838b5;
  padding-top: 2px;
  padding-bottom: 2px;
  margin-bottom: 0;
}

.category-title ~ ul {
  margin-top: 0;
}

.preset-select {
  margin-bottom: 20px;
}

.code-group {
  border: 1px solid #d7d7d7;
  margin-bottom: 20px;
}

.code-group ul {
  margin-bottom: 0;
}

ul {
  list-style-type: none;
  padding-left: 0;
}

ul li {
  cursor: pointer;
  color: #262626;
  transition: 0.1s;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  outline: none;
  display: block;
  min-width: 280px;
  white-space: nowrap;
  padding-right: 15px;
  text-align: left;
}

ul li:nth-child(odd) {
  background: #f3f3f3;
}

ul li:not(.disabled):hover {
  background: #3eaf7c;
  color: #fff;
}

ul li.checked:hover {
  background: #3eaf7c;
  color: #fff;
}

ul li.checked {
  background: #434343;
  color: #fff;
}

ul li.disabled {
  background: #c7c7c7;
  color: #767676;
}

ul li.disabled:hover {
  cursor: not-allowed;
}

li {
  position: relative;
  padding-left: 26px;
}

li::before {
  content: '';
  position: absolute;
  border-color: #e7e7e7;
  border-style: solid;
  border-width: 2px;
  border-radius: 50%;
  left: 6px;
  top: 6px;
  height: 10px;
  width: 10px;
}

li:not(.disabled):not(.checked):hover::before {
  border-color: #fff;
  background-color: #1fa76e;
}

li.checked::before {
  border-color: #fff;
  background-color: #d85e55;
}

@media screen and (max-width: 400px) {
  ul li {
    min-width: 180px;
  }
}
</style>