<template>
  <b-form-input
    v-if="singleLine"
    v-model="object.value"
    :disabled="disabledMode || locked"
    :required="required"
    :state="state"
    :type="type"
    @input="input"
  />
  <b-form-textarea
    v-else
    v-model="object.value"
    :disabled="disabledMode || locked"
    :required="required"
    :state="state"
    :type="type"
    @input="input"
  />
</template>

<script lang="ts">
import Vue, { PropType } from 'vue';

import { BFormInput, BFormTextarea } from 'bootstrap-vue';

import type { UserObject } from '@coscine/api-client/dist/types/Coscine.Api.User';
import type { NamedNode, Quad_Object } from 'rdf-js';
import { prefixes } from '@zazuko/rdf-vocabularies';
import factory from 'rdf-ext';

export default Vue.extend({
  name: 'InputTextField',
  components: {
    BFormInput,
    BFormTextarea,
  },
  props: {
    locked: {
      default: false,
      type: Boolean,
    },
    required: {
      default: false,
      type: Boolean,
    },
    singleLine: {
      default: false,
      type: Boolean,
    },
    entry: {
      required: true,
      type: Object as PropType<Quad_Object>,
    },
    dataType: {
      default: () => factory.namedNode(prefixes.xsd + 'string'),
      type: Object as PropType<NamedNode<string>>,
    },
    fixedValueMode: {
      default: false,
      type: Boolean,
    },
    disabledMode: {
      default: false,
      type: Boolean,
    },
    state: {
      type: [Boolean, Object],
      default: null,
    },
    userReceiver: {
      default: () => {
        return async () => ({} as UserObject);
      },
      type: Function as PropType<() => Promise<UserObject>>,
    },
  },
  data() {
    return {
      object: factory.literal('', this.dataType),
    };
  },
  computed: {
    type(): string {
      const dataType = this.dataType.value;
      if (dataType.endsWith('#dateTime')) {
        return 'datetime-local';
      } else if (
        dataType.endsWith('#byte') ||
        dataType.endsWith('#int') ||
        dataType.endsWith('#short') ||
        dataType.endsWith('#integer') ||
        dataType.endsWith('#long') ||
        dataType.endsWith('#unsignedByte') ||
        dataType.endsWith('#unsignedShort') ||
        dataType.endsWith('#unsignedInt') ||
        dataType.endsWith('#unsignedLong')
      ) {
        return 'number';
      }
      return 'text';
    },
  },
  watch: {
    entry() {
      this.loadData();
    },
  },
  mounted() {
    // take whatever is defined in metadata now and try to get the content if we are not in fixed value mode
    this.replacePlaceholder();
    this.loadData();
  },
  methods: {
    input() {
      if (this.type === 'datetime-local') {
        this.object.value += ':00';
      }
      this.$emit('input', this.object);
    },
    loadData() {
      if (this.object.value !== this.entry.value) {
        this.object.value = this.entry.value;
      }
    },
    replacePlaceholder() {
      if (!this.fixedValueMode) {
        if (this.entry.value === '{ME}') {
          this.retrieveUser();
        }
      }
    },
    async retrieveUser() {
      try {
        const user = await this.userReceiver();
        if (user.displayName) {
          this.object.value = user.displayName;
          this.$emit('input', this.object);
        }
      } catch (e) {
        // No user exists
        console.error(e);
      }
    },
  },
});
</script>

<style scoped></style>