<template>
  <div
    class="vc-form-radio"
    :class="[ disabled, otherClasses, colorClasses ]"
    @keydown.space.prevent
  >
    <label
      :for="labelId"
      :tabindex="disabled ? -1 : 0"
      class="vc-form-radio-label"
      @keyup.stop.prevent="changeChecked"
      @click.prevent="changeModel"
    >
      <input
        :id="labelId"
        v-model="model"
        :value="value"
        :disabled="disabled"
        :data-test="`radio-${dataTestName}`"
        :name="groupName"
        tabindex="-1"
        class="vc-form-radio-input"
        type="radio"
      >
      <span
        class="vc-form-icon-sign"
        :class="{ 'vc-icon-checkmark-solid text-white': model === value }"
      />
      <span
        v-if="$slots.default || label"
        class="vc-form-radio-label-text"
      >
        <slot>
          <div
            class="vc-radio-label"
            :class="radioLabelClass || RADIO_DEFAULT_LABEL_CLASS"
          >
            <div class="text-overflow">
              {{ label }}
            </div>
          </div>
        </slot>
      </span>
    </label>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { VcRadioTypes } from './VcRadio.types'
import color from '@/mixins/input/color.mixin'

const RADIO_DEFAULT_LABEL_CLASS = 'vc-radio-default-label'

export default defineComponent({
  name: 'VcRadio',
  mixins: [color],
  model: {
    prop: 'modelValue'
  },
  props: {
    modelValue: {
      type: [String, Number, Boolean] as PropType<VcRadioTypes>,
      default: '',
      description: 'Radio value'
    },
    value: {
      type: String,
      default: '',
      description: 'Static Radio value'
    },
    groupName: {
      type: String,
      default: '',
      description: 'Radio group name'
    },
    disabled: {
      type: Boolean,
      default: false,
      description: 'Whether VcRadio is disabled'
    },
    checked: {
      type: Boolean,
      default: false,
      description: 'Is Radio checked'
    },
    label: {
      type: String,
      default: '',
      description: 'Radio label'
    },
    iconType: {
      type: String,
      default: 'radio',
      description: 'Radio icon type: radio | checkbox'
    },
    borderless: {
      type: Boolean,
      default: false,
      description: 'Icon border state'
    },
    radioLabelClass: {
      type: String,
      default: '',
      description: 'Radio label classes'
    },
    handUpdate: {
      type: Boolean,
      default: false
    },
    dataTestName: {
      type: String,
      default: 'default'
    },
    onInput: {
      type: Function,
      default: null,
      description: 'Temporary @input method'
    }
  },
  emits: ['input', 'update:modelValue'],
  data () {
    return {
      labelId: '',
      model: '' as VcRadioTypes,
      RADIO_DEFAULT_LABEL_CLASS,
      colorClass: 'vc-radio-color-'
    }
  },
  computed: {
    colorClasses (): string {
      const colorClass = this.color ? (this.colorClass + this.color) : ''

      return [
        colorClass
      ].join(' ')
    },
    otherClasses () {
      const result = []
      switch (this.iconType) {
        default:
        case 'radio':
          result.push('view-radio')
          break
        case 'checkbox':
          result.push('view-checkbox')
          break
      }
      if (this.borderless) {
        result.push('borderless')
      }
      return result.join(' ')
    }
  },
  watch: {
    modelValue: {
      handler (newV: VcRadioTypes, oldV: VcRadioTypes) {
        if (newV !== oldV || !oldV) {
          this.model = newV
        }
      },
      immediate: true
    },
    model (newV: VcRadioTypes) {
      if (this.handUpdate || newV !== this.value) {
        return
      }
      this.update(newV)
    }
  },
  created () {
    this.labelId = Math.random()
      .toString(16)
      .slice(2)
    if (this.checked) {
      this.update(this.value)
    }
  },
  methods: {
    changeModel (): void {
      if (this.disabled) {
        return
      }
      this.model = this.value
      if (this.handUpdate) {
        this.update(this.model)
      }
    },
    changeChecked (e: KeyboardEvent): void {
      if (e.key === '32' || e.keyCode === 32) {
        this.changeModel()
      }
    },
    update (value: VcRadioTypes): void {
      if (this.$attrs && this.$attrs.onInput) {
        this.$emit('input', value)
      } else if (this.onInput && typeof this.onInput === 'function') {
        this.onInput(value)
      } else {
        this.$emit('update:modelValue', value)
      }
    }
  }
})
</script>

<style lang="scss" scoped>
@import "VcRadio";
</style>
