<template>
  <span
    :class="[{
      'mm-input--prefix': $slots.prefix || prefixIcon,
      'mm-input--suffix': $slots.suffix || suffixIcon,
      'mm-input-addon-wrapper': $slots.before || $slots.after
    }, themeClasses]"
    class="mm-input">
    <span
      v-if="$slots.before"
      class="mm-input-addon">
      <slot name="before"></slot>
    </span>

    <span class="mm-input-affix-wrapper">
      <span
        v-if="$slots.prefix || prefixIcon"
        :class="{
          'mm-input-prefix--icon': prefixIcon
        }"
        class="mm-input-prefix">
        <slot name="prefix">
          <ui-icon
            :name="prefixIcon"
            fill="#b0adab"></ui-icon>
        </slot>
      </span>
      <input
        ref="input"
        v-model="localValue"
        v-bind="attrs"
        class="mm-input-inner"
        v-on="listeners"
        @focus="handleSelect"
        @input="handleInput"
        @keydown.enter="handleEnter"
        @change="$emit('change', $event, $event.target.value)" />
      <span
        v-if="$slots.suffix || suffixIcon"
        :class="{
          'mm-input-suffix--icon': suffixIcon
        }"
        class="mm-input-suffix">
        <slot name="suffix">
          <ui-icon
            :name="suffixIcon"
            fill="#b0adab"></ui-icon>
        </slot>
      </span>
    </span>

    <span
      v-if="$slots.after"
      class="mm-input-addon">
      <slot name="after"></slot>
    </span>
  </span>
</template>

<script>
import Icon from "../icon"
import input from "../../mixins/input"
import themeSize from "../../mixins/theme-size"
import { getListeners } from "../../utils/helper"

import config from "../../managers/config"

config.defaults({
  "Input.composition": false,
})

export default {
  name: "mm-input",
  components: {
    "ui-icon": Icon,
  },
  mixins: [input, themeSize],
  inheritAttrs: false,
  model: {
    prop: "value",
    event: "input",
  },
  props: {
    type: {
      type: String,
      default: "text",
      validator(val) {
        return ["text", "password", "number"].includes(val)
      },
    },
    value: {
      type: [String, Number],
      default: "",
    },
    selectOnFocus: {
      type: Boolean,
      default: false,
    },
    composition: {
      type: Boolean,
      default: () => config.get("Input.composition"),
    },
    onEnter: {
      type: Function,
      default() {},
    },
    suffixIcon: String,
    prefixIcon: String,
    autoTrim: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      localValue: this.value,
      listeners: getListeners(["click", "focus", "blur", "keyup", "keydown", "keypress"], this),
    }
  },
  computed: {
    attrs() {
      return {
        ...this.$attrs,
        type: this.type,
        name: this.realName,
        disabled: this.realDisabled,
        readonly: this.realReadonly,
      }
    },
  },
  watch: {
    value(val) {
      if (this.autoTrim) {
        if (String(val).trim() !== String(this.localValue).trim()) {
          this.localValue = val
        }
      } else {
        this.localValue = val
      }
    },
    localValue(newVal, oldVal) {
      if (this.autoTrim) {
        if (String(newVal).trim() !== String(oldVal).trim()) {
          this.$emit("input", String(newVal).trim())
        }
      } else {
        this.$emit("input", newVal)
      }
    },
  },
  methods: {
    handleSelect(e) {
      if (this.selectOnFocus) {
        e.target.select()
      }
    },
    handleInput(e) {
      if (this.composition || this.localValue !== this.value) {
        this.localValue = e.target.value
      }
    },
    handleEnter(e) {
      this.$emit("enter", e)
      this.onEnter(e)
    },
    focus() {
      this.$refs.input.focus()
    },
    blur() {
      this.$refs.input.blur()
    },
    select() {
      this.$refs.input.select()
    },
  },
}
</script>
