<template>
    <div class="switch">
        <input :id="id" :ref="id" type="checkbox" :class="doubletoggle ? 'tgl tgl-flat both' : 'tgl tgl-flat'" @change="onToggle"/>
        <label :for="id" class="tgl-btn" v-show="editable"></label>
        <span v-html="labelText" v-if="showlabel || !editable" :class="editable ? 'normal' : 'readonly'"></span>
    </div>
</template>

<script>
import { isEmpty } from 'lodash'
/**
* Generates switch input type, an alternative to checkboxes and input where only two values are sent to server
*/
export default {
    name: 'CustomSwitch',
    props: {
        // Unique identifier
        id: {
            default: 'sw',
            type: String,
            required: true
        },
        // Value to be sent to server when switch is in ON state
        valon: {
            default: 'YES',
            type: String
        },
        // Value to be sent to server when switch is in OFF state
        valoff: {
            default: 'NO',
            type: String
        },
        // Text label display for ON state
        texton: {
            default: 'YES',
            type: String
        },
        // Text label display for OFF state
        textoff: {
            default: 'NO',
            type: String
        },
        // Control to toggle text display
        showlabel: {
            default: false,
            type: Boolean
        },
        // Enables two way binding
        value: {
            default: null
        },
        // Boolean flag to indicate editable state or not.
        editable: {
            default: true
        },
        // If switch has to be disabled
        disabled: {
            default: false,
            type: Boolean
        },
        // Both side toggle behaves as ON
        doubletoggle: {
            default: false,
            type: Boolean
        }
    },
    data () {
        return {
            val: '',
            labelText: ''
        }
    },
    methods: {
        onToggle () {
            if (this.$sw.checked) {
                this.val = this.valon
                this.labelText = this.texton
            } else {
                this.val = this.valoff
                this.labelText = this.textoff
            }
            this.$emit('input', this.val)
            this.$emit('change', this.val)
        },
        forceToggle () {
            // If the switch is disabled, temporarily enable it and reset back after the value is changed
            let attr = this.$sw.getAttribute('disabled')
            if (!isEmpty(attr) && attr !== false) {
                this.$sw.removeAttribute('disabled')
                this.$sw.click()
                this.$sw.setAttribute('disabled', true)
            } else {
                this.$sw.click()
            }
        }
    },
    mounted () {
        this.$sw = this.$refs[this.id]
        if (!this.$sw.checked && this.value == this.valon) {
            this.forceToggle()
        } else {
            this.val = this.valoff
            this.labelText = this.textoff
            this.$emit('input', this.val)
        }
        if (this.disabled) {
            this.$sw.setAttribute('disabled', true)
        }
        this.$events.on('switch|' + this.id, (d) => {
            if (d.task.toLowerCase() == 'update') {
                if (d.val != null) {
                    if ((d.val === this.valon && !this.$sw.checked) || (d.val === this.valoff && this.$sw.checked)) {
                        this.forceToggle()
                    }
                }
            } else if (d.task.toLowerCase() === 'control' && d.val.toLowerCase() === 'disable') {
                this.$sw.setAttribute('disabled', true)
            } else if (d.task.toLowerCase() === 'control' && d.val.toLowerCase() === 'enable') {
                this.$sw.removeAttribute('disabled')
            }
        })
    },
    beforeDestroy () {
        this.$events.off('switch|' + this.id)
    },
    watch: {
        value (n, o) {
            if ((n === this.valon && !this.$sw.checked) || (n === this.valoff && this.$sw.checked)) {
                this.forceToggle()
            }
        }
    }
}
</script>
