<template>
  <div class="schema-input">
    <select v-if="type == 'enum'" v-model="valueCopy" class="form-control" :disabled="!!schema.isReadOnly">
      <option></option>
      <option v-for="opt in schema.options" :key="opt.key" :value="opt.key">{{ opt.displayName || opt.key }}</option>
    </select>

    <template v-if="type == 'enum-radio'">
      <div class="btn-group">
        <label v-for="opt in schema.options" :key="opt.key" class="btn" :class="[valueCopy === opt.key ? 'btn-primary': 'btn-outline-primary']">
          <input type="radio" :name="'radio' + _uid" :value="opt.key" v-model="valueCopy" class="custom-control-input">
          <span>{{ opt.displayName || opt.key }}</span>
        </label>
      </div>
    </template>

    <template v-if="type == 'object'">
      <!--
        I keep this case for easier debugging. I'm not 100% sure that this case doesn't exist anymore.
        This happens when you use a `<schema-field ...></schema-field>` for an complex object. Use a
        `<schema-component-part ...></schema-component-part>` instead.
      -->Als het goed is komt deze case niet meer voor. Mocht je dit toch zien, neem dan contact op met het NLO team bij Q42.
    </template>

    <template v-if="type == 'array'">
      <div v-for="(item, key) in valueCopy" :key="key" class="vue-delete-item mb-1">
        <schema-input :schema="{...schema.items, title: schema.title}" v-model="valueCopy[key]"></schema-input>
        <button type="button" class="btn btn-sm btn-outline-danger vue-delete-button" @click="deleteItem(key)">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>

      <div :class="{'mt-2': valueCopy.length}">
        <schema-add-buttons v-model="valueCopy" :has-list="true" :schema="schema.items"
                            v-if="(!schema.maxLength || valueCopy.length < schema.maxLength) && !schema.isReadOnly"></schema-add-buttons>
      </div>
    </template>

    <template v-if="type == 'boolean'">
      <div class="btn-group" v-if="!schema.isReadOnly">
        <label class="btn" :class="[valueCopy ? 'btn-primary': 'btn-outline-primary']">
          <input type="radio" :name="'radio' + _uid" :value="true" v-model="valueCopy" class="custom-control-input">
          <span>Ja</span>
        </label> <label class="btn" :class="[!valueCopy ? 'btn-primary': 'btn-outline-primary']">
          <input type="radio" :name="'radio' + _uid" :value="false" v-model="valueCopy" class="custom-control-input">
          <span>Nee</span>
        </label>
      </div>

      <input v-if="!!schema.isReadOnly" class="form-control" :value="value ? 'Ja' : 'Nee'" readonly>
    </template>

    <dynamic-tag-input v-if="type == 'string' || type == 'textarea' || type == 'markdown'" @input="onInput" :type="type" :schema="schema" :value="hasValue ? valueCopy : ''" :preview="schema.title"/>
    <input v-if="type === 'number'" class="form-control" type="number" :value="hasValue ? valueCopy : ''" :placeholder="schema.title" :required="!!schema.required" :readonly="!!schema.isReadOnly" @input="onNumberInput" />

    <component v-if="type == 'other'" :is="schema.format" v-model="valueCopy" :schema="schema" :required="!!schema.required" :readonly="!!schema.isReadOnly"></component>

    <schema-validator :value="valueCopy" :schema="schema"></schema-validator>
    <validator v-if="schema.type == 'integer'" :test="!valueCopy || !isNaN(parseInt(valueCopy))">
      {{schema.title}} moet een getal zijn
    </validator>
    <validator v-if="schema.type == 'number'" :test="!valueCopy || !isNaN(parseFloat(valueCopy))">
      {{schema.title}} moet een getal zijn
    </validator>
  </div>
</template>

<style lang="scss" scoped>
  .schema-input {
    position: relative;
  }

  .btn-group .btn-outline-primary span {
    opacity: .6;
  }
</style>

<script>
import { ValueSyncMixin } from '../shared/value-sync-mixin.js';
import * as formElements from '../shared/form/all.js';
import dynamicTagInput from '../shared/dynamic-tag-input.vue';
import schemaAddButtons from './schema-add-buttons.vue';
import schemaValidator from './schema-validator.vue';

export default {
  name: 'schema-input',
  docs: `Kiest de juiste input op basis van het JSON schema, met bijbehorende validatieregels.`,
  mixins: [ValueSyncMixin],
  props: {
    value: {
      required: true,
      demoValue: 'Hallo!',
    },
    schema: {
      type: Object,
      required: true,
      demoValue: () => ({
        type: 'string',
        format: 'textarea',
      }),
    },
  },
  watch: {
    // overwrite valueCopy from ValueSyncMixin
    valueCopy (newValue) {
      // format the input value
      let formattedValue = newValue;

      if (this.type == 'number' && this.schema.type == 'integer') {
        formattedValue = parseInt(formattedValue, 10);
      }

      if (this.type == 'string' || this.type == 'textarea') {
        if (formattedValue === '' && !this.schema.required) {
          // example use case: string with C# UrlAttribute is valid on server when it is 'null' or starting with 'https/http/ftp'. Empty string is not valid.
          formattedValue = null;
        }
      }

      if (typeof formattedValue == 'number' && isNaN(formattedValue))
        formattedValue = null;

      this.$emit('input', formattedValue); // vue syntax: update prop 'value' in the parent
    },
  },
  computed: {
    type () {
      if (this.schema.format == 'string-input') return 'string';
      if (this.schema.format == 'textarea') return 'textarea';
      if (this.schema.format == 'markdown') return 'markdown';
      if (this.schema.format) return 'other';
      if (this.schema.enum) {
        var opts = this.schema.options.map(opt => opt.displayName || opt.key).toString();
        return opts.length < 30 ? 'enum-radio' : 'enum';
      }
      if (this.schema.properties) return 'object'; // obsolete, can be removed in the future. See also comment in template
      if (this.schema.type == 'array') return 'array';
      if (this.schema.type == 'boolean') return 'boolean';
      if (this.schema.type == 'number' || this.schema.type == 'integer') return 'number';
      return 'string';
    },
    hasValue() {
      return this.valueCopy !== undefined && this.valueCopy !== null && this.valueCopy !== '';
    }
  },
  methods: {
    deleteItem(index) {
      this.valueCopy.splice(index, 1);
    },
    onInput(input) {
      this.valueCopy = input;
      this.$emit('input', input);
    },
    onNumberInput(event) {
      this.onInput(event.target.value);
    }
  },
  components: {
    ...formElements,
    schemaAddButtons,
    schemaValidator,
    dynamicTagInput,
  },
};
</script>
