<template>
  <snt-text-field
    ref="input"
    v-model="phone"
    type="tel"
    :value="value"
    :rules="rules"
    :prefix="dialCode"
    :outlined="outlined"
    :dense="dense"
    :hidden-details="false">
    <template #append>
      <v-fade-transition>
        <snt-icon
          v-if="phoneObject.valid"
          icon="mdi-check"
          color="success" />
      </v-fade-transition>
    </template>
  </snt-text-field>
</template>

<script>
import PhoneNumber from 'awesome-phonenumber'
import { VFadeTransition } from 'vuetify/lib'
import allCountries from '../../resources/json/countries'

export default {
  components: { VFadeTransition },
  props: {
    value: {
      type: String,
      default: ''
    },
    rules: {
      type: Array,
      default: () => ([])
    },
    outlined: {
      type: Boolean,
      default: false
    },
    dense: {
      type: Boolean,
      default: false
    },
    defaultCountry: {
      type: String,
      default: () => 'TH'
    }
  },
  data () {
    return {
      mode: 'national',
      phone: '',
      activeCountry: { iso2: '', dialCode: '' },
      allCountries
    }
  },
  computed: {
    dialCode () {
      return this.activeCountry ? `+${this.activeCountry.dialCode}` : null
    },
    parsedMode () {
      if (this.mode) {
        if (!['international', 'national'].includes(this.mode)) {
          console.error('Invalid value of prop "mode"')
        } else {
          return this.mode
        }
      }
      if (!this.phone || this.phone[0] !== '+') {
        return 'national'
      }
      return 'international'
    },
    phoneObject () {
      const result = PhoneNumber(this.phone || '', this.activeCountry.iso2).toJSON()
      Object.assign(result, {
        isValid: result.valid,
        country: this.activeCountry
      })
      if (!this.phone) {
        return {
          ...result,
          number: {
            input: ''
          }
        }
      }
      return result
    },
    phoneText () {
      let key = 'input'
      if (this.phoneObject.valid) {
        key = this.parsedMode
      }
      return this.phoneObject.number[key] || ''
    }
  },
  watch: {
    value () {
      this.phone = this.value
    },
    phone (newValue, oldValue) {
      if (newValue) {
        if (newValue[0] === '+') {
          const code = PhoneNumber(newValue).getRegionCode()
          if (code) {
            this.activeCountry = this.findCountry(code) || this.activeCountry
          }
        }
      }
      if (oldValue && this.cursorPosition < oldValue.length) {
        this.$nextTick(() => {
          this.setCaretPosition(this.$refs.input, this.cursorPosition)
        })
      }
      this.$emit('input', this.phoneText, this.phoneObject)
    },
    'phoneObject.valid': function (value) {
      if (value) {
        this.phone = this.phoneText
      }
      this.$emit('validate', this.phoneObject)
    }
  },
  mounted () {
    this.initializeCountry()
  },
  methods: {
    initializeCountry () {
      this.activeCountry = this.findCountry(this.defaultCountry)
    },
    findCountry (iso = '') {
      return this.allCountries.find(
        (country) => country.iso2 === iso.toUpperCase()
      )
    },
    setCaretPosition (ctrl, pos) {
      if (ctrl.setSelectionRange) {
        ctrl.focus()
        ctrl.setSelectionRange(pos, pos)
      } else if (ctrl.createTextRange) {
        const range = ctrl.createTextRange()
        range.collapse(true)
        range.moveEnd('character', pos)
        range.moveStart('character', pos)
        range.select()
      }
    }
  }
}
</script>
