<template>
  <v-layout row>
    <div class="field-name">
      <b>{{ name }}</b>
    </div>

    <div :class="['field-value', oneLine ? 'one-line' : '']">
      <span
        v-if="hasPermission && isEditable">
        <v-text-field
          ref="edit"
          :value="value"
          :rules="rules"
          :hint="hint"
          :loading="loading"
          class="base-editable-field"
          prepend-icon="check"
          @input="updateDirtyValue"
          @click:prepend="makeFieldNotEditable"
          @keyup.enter="makeFieldNotEditable"
          @keyup.esc="cancelEdition"/>
      </span>
      <span v-else>
        <v-input
          :class="['non-base-editable-field', !hasPermission && 'prevent-editing']"
          prepend-icon="edit"
          @click:prepend="makeFieldEditable">
          <span v-if="showAsHtml" v-html="value || '-'"/>
          <span v-else>{{ value || "-"}}</span>
        </v-input>
      </span>
    </div>
  </v-layout>
</template>

<script>
export default {
  name: 'BaseEditableField',
  props: {
    name: {
      type: String,
      required: true
    },
    model: {
      type: Object,
      required: true
    },
    field: {
      type: String,
      required: true
    },
    hint: {
      type: String,
      default: ''
    },
    loading: {
      type: Boolean,
      default: false
    },
    rules: {
      type: Array,
      default: () => []
    },
    oneLine: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: 'large',
      validator: value => ['small', 'large'].includes(value)
    },
    hasPermission: {
      type: Boolean,
      default: true
    },
    showAsHtml: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      dirtyValue: this.value,
      isEditable: false,
      originalValue: null,
      showEditIcon: false
    }
  },
  computed: {
    value: {
      get () {
        return this.$get(this.model, this.field, '')
      },
      set (value) {
        this.$set(this.model, this.field, value)
      }
    }
  },
  watch: {
    loading (newValue, oldValue) {
      if (oldValue && !newValue && this.isEditable) {
        this.isEditable = false
      }
    }
  },
  methods: {
    updateDirtyValue (value) {
      this.dirtyValue = value
    },
    makeFieldEditable () {
      if (this.hasPermission) {
        this.isEditable = true
        this.$nextTick(() => {
          this.$refs.edit.focus()
        })
        this.originalValue = this.value
      }
    },
    makeFieldNotEditable () {
      if (this.$refs.edit.validate()) {
        if (this.originalValue !== this.dirtyValue) {
          this.$emit('update-value', {
            [this.field]: this.dirtyValue
          })
        }
      }
    },
    cancelEdition () {
      this.value = this.originalValue
      this.isEditable = false
    }
  }
}
</script>

<style lang="scss">
.edit-icon {
  font-size: 16px;
  margin: 0;
  height: 16px;
}
.base-editable-field, .non-base-editable-field {
  &.v-input {
    font-size: 12px;
    margin: 0;
    margin-left: -30px;
    input {
      padding: 0px;
    }
    .v-icon {
      font-size: 20px;
      margin-top: -15px;
      margin-right: -15px;
      color: transparent;
      &:hover {
        color: rgba(0,0,0,.54);
      }
    }
  }
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.non-base-editable-field {
  .v-input {
    padding-top: 1px;
    padding-bottom: 1px;
    margin-top: 0px;
  }
  &.prevent-editing {
    .v-icon:hover {
      cursor: default;
      color: transparent;
    }
  }
}
.v-input .v-input__slot {
  margin-bottom: 0px;
}
.field-value {
  &.one-line {
    overflow-x: auto;
    span {
      overflow-x: auto;
    }
  }
}

.field-name {
  float: right;
  flex: 0 0 80px;
  overflow-x: auto;
  span {
    overflow-x: auto;
  }
}
</style>
