<template>
  <div class="project-creation-window">
    <div class="content">
      <h1 class="headline">Create Project</h1>

      <text-input placeholder="Name"
                  v-model="name"
                  :error="nameError"
                  @clearError="nameError = false">
        Name
      </text-input>

      <textarea-input placeholder="Description"
                      v-model="description"
                      :error="descriptionError"
                      @clearError="descriptionError = false">
        Description
      </textarea-input>

      <select-input :values="availableModels"
                    v-model="model">
        Model
      </select-input>

      <model-abilities :model="currentModel"/>

      <select-input :values="availableLabels"
                    v-model="label">
        Label Provider
      </select-input>

      <text-input placeholder="path to folder (leave empty to disable)"
                  v-model="external"
                  @change="checkDirectory">
        External Storage
      </text-input>

      <div class="external">
        <template v-if="externalPathInformation !== null">
          <template v-if="externalPathInformation.exists">
            The given directory contains {{ externalPathInformation.count }} files.<br>
          </template>
          <template v-else>
            The given directory is not valid.<br>
          </template>
        </template>
        The external storage mode disables file uploads and loads them from the given directory instead.
      </div>
    </div>

    <button-row class="footer">
      <button-input @click="createProject" type="primary"
                    :disabled="externalPathInformation !== null && !externalPathInformation.exists">
        Create Project
      </button-input>

      <button-input @click="$emit('cancel', null)">
        Cancel
      </button-input>
    </button-row>
  </div>
</template>

<script>
import TextInput from "@/components/base/text-input";
import TextareaInput from "@/components/base/textarea-input";
import SelectInput from "@/components/base/select-input";
import ButtonInput from "@/components/base/button-input";
import ButtonRow from "@/components/base/button-row";
import ModelAbilities from "@/components/models/model-abilities";

export default {
  name: "project-creation-window",
  components: {ModelAbilities, ButtonRow, ButtonInput, SelectInput, TextareaInput, TextInput},
  props: ['status', 'socket'],
  created: function () {
    // get data
    this.getModels();
    this.getLabels();

    // subscribe to changes
    this.$root.socket.on('connect', this.getModels);
    this.$root.socket.on('create-model', this.addModel);
    this.$root.socket.on('remove-model', this.removeModel);

    this.$root.socket.on('connect', this.getLabels);
  },
  destroyed: function () {
    this.$root.socket.off('connect', this.getModels);
    this.$root.socket.off('create-model', this.addModel);
    this.$root.socket.off('remove-model', this.removeModel);

    this.$root.socket.off('connect', this.getLabels);
  },
  data: function () {
    return {
      name: '',
      nameError: false,
      description: '',
      descriptionError: false,

      models: [],
      model: null,

      labels: [],
      label: null,

      external: '',
      externalPathInformation: null
    }
  },
  methods: {
    getModels: function () {
      this.models = [];
      this.$root.socket.get('/models')
          .then(response => response.json())
          .then(models => models.forEach(this.addModel));
    },
    addModel: function (model) {
      for (let m of this.models)
        if (m.identifier === model.identifier)
          return;

      this.models.push(model);
    },
    removeModel: function (model) {
      for (let i = 0; i < this.models.length; i++) {
        if (this.models[i].identifier === model.identifier) {
          this.models.splice(i, 1);
          break;
        }
      }

      if (model.identifier === parseInt(this.model) && this.models.length > 0) {
        this.model = this.models[0].identifier;
      }
    },
    getLabels: function () {
      this.$root.socket.get('/label_providers')
          .then(response => response.json())
          .then(labels => this.labels = labels);
    },
    checkDirectory: function (value) {
      if (!value) {
        this.externalPathInformation = null;
        return;
      }

      this.$root.socket.post('/folder', {
        'folder': this.external
      })
          .then(response => response.json())
          .then(data => this.externalPathInformation = data);
    },
    createProject: function () {
      // check input
      this.nameError = !this.name;
      this.descriptionError = !this.description;

      if (this.nameError || this.descriptionError)
        return;

      // create project
      // TODO then / error
      this.$root.socket.post('/projects', {
        name: this.name,
        description: this.description,
        model: parseInt(this.model),
        label: parseInt(this.label),
        external: this.external === '' ? null : this.external
      });

      // close project creation window
      this.$emit('cancel', null);
    }
  },
  computed: {
    availableModels: function () {
      return this.models.map(m => {
        return {
          name: m.name,
          value: m.identifier,
        }
      }).sort((m1, m2) => m1.name < m2.name ? -1 : +1);
    },
    currentModel: function () {
      for (let model of this.models)
        if (model.identifier === parseInt(this.model))
          return model;

      return false;
    },
    availableLabels: function () {
      let result = [];

      // add label providers
      for (let label of this.labels) {
        result.push({
          name: label.name,
          value: label.identifier,
        });
      }

      // sort
      result.sort((a, b) => {
        if (a.name.includes(b.name))
          return +1;
        if (b.name.includes(a.name))
          return -1;
        if (a.name > b.name)
          return +1;
        else
          return -1;
      });

      // add `None` option
      result.unshift({
        name: 'None',
        value: null
      });

      return result;
    }
  },
  watch: {
    availableModels: function (newValue) {
      if (this.model === null && newValue.length > 0) {
        this.model = newValue[0].value;
      }
    },
    availableLabels: function (newValue) {
      if (this.label === null && newValue.length > 0) {
        this.label = newValue[0].value;
      }
    },
  }
}
</script>

<style scoped>
.project-creation-window {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
}

.content {
  overflow: auto;
  padding: 1rem;
  height: 100%;
  flex-grow: 1;
}

.content > :not(h1) {
  margin-bottom: 0.6rem;
}

/deep/ .content textarea {
  height: 4rem;
}

.model-abilities {
  font-size: 80%;
}

.external {
  font-size: 80%;
}

.footer {
  flex-grow: 0;
  padding: 1rem;
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
}
</style>
