/*
 * Name: inputTag
 * Author: cshaptx4869
 * Project: https://github.com/cshaptx4869/inputTag
 */
layui.define(['form'], function (exports) {
    "use strict";

    var $ = layui.$, form = layui.form, defaultOption = {
        elem: '.fairy-tag-input',
        theme: ['fairy-bg-red', 'fairy-bg-orange', 'fairy-bg-green', 'fairy-bg-cyan', 'fairy-bg-blue', 'fairy-bg-black'],
        data: [],
        removeKeyNum: 8,
        createKeyNum: 13,
        upSelectKeyNum: 38,
        downSelectKeyNum: 40,
        escKeyNum: 27,
        permanentData: [],
        autoComplete: undefined
    }, _instances = {};
    
    var InputTag = function (options) {
        this.render(options);
    }
    
    InputTag.prototype.autoCompleteIndex = 0;
    
    InputTag.prototype.render = function (options) {
        this.init(options);
        this.listen();
    }
    
    InputTag.prototype.init = function (opt) {
        var spans = '', that = this;
        this.options = $.extend(defaultOption, opt);
        this.elem = $(this.options.elem);
        _instances[this.options.elem] = this;
        this.options.index = this.getIndex();
        !this.elem.attr('placeholder') && this.elem.attr('placeholder', '添加标签');
        $.each(this.options.data, function (index, item) {
            spans += that.spanHtml(item);
        });
        this.elem.before(spans);
        this.initAutoComplete();
    }
    
    InputTag.prototype.initAutoComplete = function () {
        var that = this, acOption = that.options.autoComplete;
        if (!acOption) return;
        that.options.autoCompleteElem = $(`<select lay-filter="tagsAutoComplete${this.options.index}" class="layui-select"></select>`);
        that.elem.after(that.options.autoCompleteElem);
        var dropdown = that.elem.siblings('.layui-form-selected').find('dd.layui-this');
        dropdown.on('click', function (){
            
        });
        form.on(`select(tagsAutoComplete${that.options.index})`, function (data) {
            acOption.select(data);
        });
        $('head').append([
            '<style>', 
            `[lay-filter="tagsAutoComplete${that.options.index}"]+div>.layui-select-title {`,
            '   display: none; height: 0',
            '}', 
            `[lay-filter="tagsAutoComplete${that.options.index}"]+div> dl {`,
            '   top: 0; margin: 0',
            '}',
            '</style>'
        ].join(''));
    }
    
    
    InputTag.prototype.autoComplete = function (e) {
        var that = this;
        if (!(that.options.autoComplete)) return;
        that.autoCompleteIndex++;
        var acOption = that.options.autoComplete;
        var inputText = that.elem.val().trim();
        if (inputText == '') return;
        $.ajax({
            url: acOption.url,
            data: {
                input: inputText
            },
            success: function (data) {
                that.options.autoCompleteElem.empty();
                if (!data || !data.length) return;
                data.forEach((i) => {
                    that.options.autoCompleteElem
                        .append($(`<option value="${i.name}">${i.name}</option>`));
                });
                layui.form.render();
                that.options.autoCompleteElem
                    .siblings('.layui-form-select')
                    .addClass('layui-form-selected')
                    .find('dd').removeClass('layui-this');
            }
        })
    }
    
    InputTag.prototype.listen = function () {
        var that = this;

        this.elem.parent().on('click', 'a', function () {
            that.removeItem($(this).parent('span'));
            return false;
        });

        this.elem.parent().on('click', function () {
            that.elem.focus();
            return false;
        });

        this.elem.on('keydown', function (event) {
            var keyNum = (event.keyCode ? event.keyCode : event.which),
                dropdown = that.elem.siblings('.layui-form-selected').find('dd');
            if (keyNum === that.options.removeKeyNum) {
                if (that.options.autoComplete && dropdown.length) {
                    dropdown.click();
                }
                else if (!that.elem.val().trim()) {
                    var closeItems = that.elem.parent().find('a');
                    if (closeItems.length) {
                        that.removeItem($(closeItems[closeItems.length - 1]).parent('span'));
                    }
                }
                else if (that.elem.val().trim()) {
                    that.elem.val('');
                    event.preventDefault()
                    return false;
                }
            } else if (keyNum === that.options.createKeyNum) {
                if (that.options.autoComplete && dropdown.length) {
                    var selectItem = that.elem.siblings('.layui-form-selected').find('dd.layui-this');
                    if (selectItem.length) {
                        that.elem.val(selectItem.attr('lay-value'));
                        that.createItem();
                        that.elem.siblings('.layui-form-selected').remove();
                        return false;
                    }
                }
                that.createItem();
            }
            else if (keyNum == that.options.upSelectKeyNum || keyNum == that.options.downSelectKeyNum) {
                if (that.options.autoComplete && dropdown.length) {
                    var dropdownList = that.elem.siblings('.layui-form-selected').find('dd');
                    if (dropdownList.length) {
                        event.preventDefault()
                        $.each(dropdownList, (i, v) => {
                            v = $(v);
                            if (v.hasClass('layui-this')) {
                                var target = i + keyNum - 39;
                                if (target >= 0 && target < dropdownList.length) {
                                    $(dropdownList[target]).addClass('layui-this');
                                    v.removeClass('layui-this');
                                }
                                return false;
                            }
                        });
                        if (!that.elem.siblings('.layui-form-selected').find('dd.layui-this').length) {
                            // 没有任何被选中
                            $(dropdownList[0]).addClass('layui-this');
                        }
                        return false;
                    }
                }
            }
            else if (keyNum == that.options.escKeyNum) {
                if (that.options.autoComplete && dropdown.length) {
                    that.elem.siblings('.layui-form-selected').remove();
                }
            }
        }).on('input', function (e) {
            that.autoComplete(e);
            return false;
        }).on('click', function (e) {
            that.autoComplete(e);
            return false;
        });

        this.onChange();
    }
    
    InputTag.prototype.createItem = function () {
        var value = this.elem.val().trim();
        if (!value) return false;
        if (!this.options.data.includes(value)) {
            this.options.data.push(value);
            this.elem.before(this.spanHtml(value));
        }
        this.elem.val('');
        this.onChange();
    }
    
    InputTag.prototype.removeItem = function (target) {
        var that = this;
        var closeSpan = target.remove(),
            closeSpanText = $(closeSpan).children('span').text();
        that.options.data.splice($.inArray(closeSpanText, that.options.data), 1);
        that.onChange();
    }

    InputTag.prototype.randomColor = function () {
        return this.options.theme[Math.floor(Math.random() * this.options.theme.length)];
    }

    InputTag.prototype.spanHtml = function (value) {
        return '<span class="fairy-tag fairy-anim-fadein ' + this.randomColor() + '">' +
            '<span>' + value + '</span>' +
            (this.options.permanentData.includes(value) ? '' : '<a href="#" title="删除标签">&times;</a>') +
            '</span>';
    }

    InputTag.prototype.onChange = function () {
        this.options.onChange && typeof this.options.onChange === 'function' && this.options.onChange(this.options.data);
    }

    InputTag.prototype.getIndex = function () {
        return Object.keys(_instances).length;
    }
    
    var that = this, itl = {
        render: function (options) {
            return new InputTag(options);
        },
        createItem: InputTag.prototype.createItem,
        index: InputTag.prototype.getIndex() + 1
    };
    exports('inputTagLay', itl);
});
