define([
    '../../core/utils/data',
    '../../core/utils/helper',
    '../../core/utils/method',
    '../../core/models/index'
], (data, helper, method, model) => {
    (function($) {
        new method('spinner', {
            init: function (element) {
                const context = this;

                if (!element.is('select')) {
                    return false;
                }

                const $selected = element.find('option:selected');
                const $spinner = $(context.$helper.parseTemplate('spinner', {
                    option: $selected.length > 0 ? $selected.text() : context.global.empty
                }));
                const attrs = element.prop('attributes');

                for (let idx in attrs) {
                    let attr = attrs[idx];
                    if (attr.name !== 'class' && attr.name !== 'style') {
                        $spinner.attr(attr.name, attr.value);
                    }
                }

                if (element.attr('class')) {
                    const regex = /input-(\w+)/gi;
                    const classFullName = element.attr('class');
                    const extractedClasses = classFullName.match();
                    if(extractedClasses !== null && extractedClasses.length > 0) {
                        let match = regex.exec(classFullName);
                        while(match !== null) {
                            let class_name = match[1];
                            $spinner.addClass('spinner-' + class_name);
                            match = regex.exec(classFullName);
                        }
                    }
                }

                $spinner.insertAfter(element);
                $spinner.ripple({
                    theme: 'dark'
                });
                element.hide();

                context.$helper.bind(element, 'focus', function (event) {
                    $spinner.focus();
                });

                context.$helper.bind(element, 'change', function (event) {
                    context.$helper.triggerHandler(element, 'update');
                });

                context.$helper.bind(element, 'update', function (event, value) {
                    const $this = $(this);
                    let $target;

                    if (value) {
                        $target = $this.find(`option[value="${value}"]`);
                    }
                    else {
                        $target = $this.find('option:selected');
                    }

                    if ($target.length < 1) {
                        $target = $this.find('option:first');
                    }

                    let text = $target.text();

                    if (text !== '') {
                        $spinner.find('.spinner-txt').text(text);
                    }

                    if (element.prop('disabled')) {
                        $spinner.addClass('spinner-disabled');
                    }

                    if (element.prop('readonly')) {
                        $spinner.addClass('spinner-readonly');
                    }
                });

                context.$helper.bind($spinner, 'click', function (event) {
                    event.preventDefault();
                    event.stopPropagation();
                    const $this = $(this);
                    const $scrollParent = $this.scrollParent();

                    context.$helper.triggerHandler(context.element.$document, 'click');
                    if ($this.hasClass('spinner-disabled') || $this.hasClass('spinner-readonly')) {
                        return false;
                    }
                    const $spinnerWrapper = $(context.$helper.parseTemplate('spinnerWrapper'));

                    element.find('option').each(function () {
                        let $this = $(this);
                        let $option = $(context.$helper.parseTemplate('spinnerOptions', {
                            value: $this.val(),
                            option: $this.text(),
                            type: ($this.prop('selected') === true && $this.text() !== '')? 'selected':'default'
                        }));

                        if ($this.prop('selected') === true) {
                            $spinner.find('.spinner-txt').text($this.text());
                        }

                        $option.ripple({
                            theme: 'dark'
                        }).appendTo($spinnerWrapper);
                    });
                    $spinnerWrapper.appendTo('body').css('position', 'absolute');
                    $spinnerWrapper.addClass('anim-start');

                    context.$helper.bind($scrollParent, 'scroll', function (event) {
                        context.$helper.triggerHandler(context.element.$window, 'resize');
                    });

                    context.$helper.bind(context.element.$window, 'resize', function () {
                        $spinnerWrapper.css({
                            top: $spinner.offset().top,
                            left: $spinner.offset().left + (($spinner.outerWidth() - $spinnerWrapper.outerWidth()) / 2)
                        });
                        if ($spinnerWrapper.offset().top + $spinnerWrapper.outerHeight() > context.element.$window.scrollTop() + context.element.$window.height()) {
                            $spinnerWrapper.children('.spinner-option').each(function () {
                                const $this = $(this);
                                $this.prependTo($spinnerWrapper);
                            });
                            $spinnerWrapper.css({
                                top: $spinner.offset().top + $spinner.outerHeight() - $spinnerWrapper.outerHeight()
                            });
                        }
                    }, true);

                    context.$helper.bind(context.element.$document, 'click', function () {
                        $spinnerWrapper.removeClass('anim-start');
                        context.$helper.promise(function () {
                            $spinnerWrapper.remove();
                        }, 100);
                        context.$helper.unbind(context.element.$window, 'resize');
                        context.$helper.unbind(context.element.$document, 'click');
                    });

                    context.$helper.bind($spinnerWrapper.find('.spinner-option'), 'click', function (event) {
                        event.preventDefault();
                        event.stopPropagation();
                        const $this = $(this);
                        const value = $this.data('value');
                        $spinnerWrapper.removeClass('anim-start');
                        context.$helper.promise(() => {
                            $spinnerWrapper.remove();
                        }, 100);
                        element.val(value);
                        context.$helper.triggerHandler(element, 'change', true);
                        context.$helper.unbind(context.element.$window, 'resize');
                        context.$helper.unbind(context.element.$document, 'click');
                    });
                });
            },
            template: {
                spinner: '<a href="#" class="spinner"><span class="spinner-txt">{option}</span><i class="spinner-arrow pe-7s-angle-down"></i></a>',
                spinnerWrapper: '<div class="spinner-wrapper"></div>',
                spinnerOptions: '<a href="#" class="spinner-option spinner-{type}" data-value="{value}">{option}</a>'
            },
            options: {
                once: true,
                empty: '선택'
            }
        });
    }(jQuery));
});