<template>
    <label role="checkbox"
           :class="checkboxClass"
           :aria-checked="model === label"
           :aria-disabled="isDisabled">
        <span :class="inputClass">
            <input ref="checkbox"
                   v-model="model"
                   :disabled="isDisabled"
                   type="checkbox"
                   class="native"
                   :value="label"
                   aria-hidden="true"
                   @change="handleChange">
        </span>
        <span :class="labelClass">
            <slot>{{label}}</slot>
        </span>
    </label>
</template>

<script>
import { prefix } from 'jdd-design/utils';
export default {
    name: `${prefix}-checkbox`,
    inject: {
        jddForm: {
            default: null
        },
        jddFormItem: {
            default: null
        },
        jddCheckboxGroup: {
            default: null
        }
    },
    props: {
        value: Boolean,
        label: [String, Number, Boolean],
        disabled: Boolean,
        name: String,
        size: String,
        id: String,
        multiTypeDepends: Array
    },
    data() {
        return {
            depends: {},
            indeterminate: false,
            checked: false
        };
    },
    watch: {
        indeterminate: function(val) {
            if (this.multiTypeDepends) {
                if (!val) {
                    this.model = this.checked;
                }
            }
        }
    },
    computed: {
        checkboxClass() {
            let checked = this.model;
            let clsNames = [`${prefix}-checkbox`];
            this.isDisabled && clsNames.push('is-disabled');
            if (this.multiTypeDepends) {
                this.walk(this.$root.$children);
                let vals = Object.values(this.depends);
                if (vals.length === this.multiTypeDepends.length) {
                    if (vals.every(m => m === true)) {
                        checked = true;
                        this.indeterminate = false;
                    } else {
                        checked = false;
                        this.indeterminate = vals.some(m => m === true);
                    }
                }
            }
            this.checked = checked;
            checked && clsNames.push('is-checked');
            this.indeterminate && clsNames.push('is-indeterminate');
            return clsNames;
        },
        inputClass() {
            let clsNames = [`${prefix}-checkbox__input`];
            this.checked && clsNames.push('jdd-icon-checked');
            this.indeterminate && clsNames.push('jdd-icon-indeterminate');
            return clsNames;
        },
        labelClass() {
            let clsNames = [`${prefix}-checkbox__label`];
            return clsNames;
        },
        model: {
            get() {
                return this.jddCheckboxGroup
                    ? this.jddCheckboxGroup.value.indexOf(this.label) > -1
                    : this.value;
            },
            set(val) {
                if (this.jddCheckboxGroup) {
                    let v = { key: this.label, value: val };
                    this.jddCheckboxGroup.setValue(v);
                    this.$refs.checkbox && (this.$refs.checkbox.checked = val);
                } else {
                    this.$refs.checkbox &&
                        (this.$refs.checkbox.checked = this.model);
                    this.checked = this.model;
                }
                this.$emit('input', val);
                if (this.multiTypeDepends) {
                    this.set(this.$root.$children, val);
                }
            }
        },
        isDisabled() {
            return (
                this.disabled ||
                (this.jddCheckboxGroup && this.jddCheckboxGroup.disabled) ||
                (this.jddForm && this.jddForm.disabled)
            );
        }
    },
    methods: {
        walk(children) {
            if (children && children.length) {
                children.forEach(item => {
                    if (this.multiTypeDepends.indexOf(item.id) > -1) {
                        this.depends[item.id] = item.model;
                    } else {
                        this.walk(item.$children);
                    }
                });
            }
        },
        set(children, value) {
            if (children && children.length) {
                children.forEach(item => {
                    if (this.multiTypeDepends.indexOf(item.id) > -1) {
                        item.model = value;
                    } else {
                        this.set(item.$children, value);
                    }
                });
            }
        },
        handleChange() {
            this.$nextTick(() => {
                this.$emit('change', this.model);
            });
            this.jddFormItem && this.jddFormItem.$emit('form.change');
        }
    },
    mounted() {
        if (this.jddCheckboxGroup) {
            this.model = this.jddCheckboxGroup.value.indexOf(this.label) > -1;
        } else {
            this.model = this.value;
        }
    }
};
</script>