/*===============================================================================
************   Autocomplete   ************
===============================================================================*/
var Autocomplete = function (params) {
    var a = this;

    // Params
    var defaults = {
        // Standalone Options
        /*
        opener: undefined,
        */
        popupCloseText: 'Close',
        backText: 'Back',
        searchbarPlaceholderText: 'Search...',
        searchbarCancelText: 'Cancel',
        openIn: 'page',
        backOnSelect: false,
        notFoundText: 'Nothing found',
        /*
        pageTitle: undefined,
        */

        // Handle Data
        /*
        source: undefined,
        limit: undefined,
        */
        valueProperty: 'id',
        textProperty: 'text',

        // Dropdown Options
        /*
        dropdownPlaceholderText: 'Type anything...',
        */
        updateInputValueOnSelect: true,
        expandInput: false,

        // Preloader
        preloaderColor: false,
        preloader: false,

        // Templates
        /*
        itemTemplate: undefined,
        navbarTemplate: undefined,
        dropdownTemplate: undefined
        dropdownItemTemplate: undefined,
        dropdownPlaceholderTemplate: undefined
        */

        // Color themes
        /*
        navbarTheme: undefined,
        formTheme: undefined,
        */

        // Callbacks
        /*
        onChange: function (a, value) - for not dropdown
        onOpen: function (a)
        onClose: function (a)
        */
    };

    params = params || {};
    for (var def in defaults) {
        if (typeof params[def] === 'undefined') {
            params[def] = defaults[def];
        }
    }
    a.params = params;

    // Opener Link & View
    if (a.params.opener) {
        a.opener = $(a.params.opener);
    }
    var view = a.params.view;
    if (!a.params.view && a.opener && a.opener.length) {
        // Find related view
        view = a.opener.parents('.' + app.params.viewClass);
        if (view.length === 0) return;
        view = view[0].f7View;
    }

    // Input
    if (a.params.input) {
        a.input = $(a.params.input);
        if (a.input.length === 0 && a.params.openIn === 'dropdown') return;
    }

    // Array with selected items
    a.value = a.params.value || [];

    // ID & Inputs
    a.id = (new Date()).getTime();
    a.inputType = a.params.multiple ? 'checkbox' : 'radio';
    a.inputName = a.inputType + '-' + a.id;

    // Is Material
    var material = app.params.material;

    // Back On Select
    var backOnSelect = a.params.backOnSelect;

    if (a.params.openIn !== 'dropdown') {
        // Item Template
        a.itemTemplate = t7.compile(a.params.itemTemplate ||
            '<li>' +
                '<label class="label-{{inputType}} item-content">' +
                    '<input type="{{inputType}}" name="{{inputName}}" value="{{value}}" {{#if selected}}checked{{/if}}>' +
                    '{{#if material}}' +
                        '<div class="item-media">' +
                            '<i class="icon icon-form-{{inputType}}"></i>' +
                        '</div>' +
                        '<div class="item-inner">' +
                            '<div class="item-title">{{text}}</div>' +
                        '</div>' +
                    '{{else}}' +
                        '{{#if checkbox}}' +
                        '<div class="item-media">' +
                            '<i class="icon icon-form-checkbox"></i>' +
                        '</div>' +
                        '{{/if}}' +
                        '<div class="item-inner">' +
                            '<div class="item-title">{{text}}</div>' +
                        '</div>' +
                    '{{/if}}' +
                '</label>' +
            '</li>'
        );
        // Page Layout
        var pageTitle = a.params.pageTitle || '';
        if (!pageTitle && a.opener && a.opener.length) {
            pageTitle = a.opener.find('.item-title').text();
        }
        var pageName = 'autocomplete-' + a.inputName;

        var navbarTheme = a.params.navbarTheme,
            formTheme = a.params.formTheme;

        // Navbar HTML
        var navbarHTML;
        var noNavbar = '', noToolbar = '', navbarLayout;

        a.navbarTemplate = t7.compile(a.params.navbarTemplate ||
            '<div class="navbar {{#if navbarTheme}}theme-{{navbarTheme}}{{/if}}">' +
                '<div class="navbar-inner">' +
                    '<div class="left sliding">' +
                        '{{#if material}}' +
                        '<a href="#" class="link {{#if inPopup}}close-popup{{else}}back{{/if}} icon-only"><i class="icon icon-back"></i></a>' +
                        '{{else}}' +
                        '<a href="#" class="link {{#if inPopup}}close-popup{{else}}back{{/if}}">' +
                            '<i class="icon icon-back"></i>' +
                            '{{#if inPopup}}' +
                            '<span>{{popupCloseText}}</span>' +
                            '{{else}}' +
                            '<span>{{backText}}</span>' +
                            '{{/if}}' +
                        '</a>' +
                        '{{/if}}' +
                    '</div>' +
                    '<div class="center sliding">{{pageTitle}}</div>' +
                    '{{#if preloader}}' +
                    '<div class="right">' +
                        '<div class="autocomplete-preloader preloader {{#if preloaderColor}}preloader-{{preloaderColor}}{{/if}}"></div>' +
                    '</div>' +
                    '{{/if}}' +
                '</div>' +
            '</div>'
        );
        navbarHTML = a.navbarTemplate({
            pageTitle: pageTitle,
            backText: a.params.backText,
            popupCloseText: a.params.popupCloseText,
            openIn: a.params.openIn,
            navbarTheme: navbarTheme,
            inPopup: a.params.openIn === 'popup',
            inPage: a.params.openIn === 'page',
            material: material,
            preloader: a.params.preloader,
            preloaderColor: a.params.preloaderColor,
        });

        // Determine navbar layout type - static/fixed/through
        if (a.params.openIn === 'page') {
            navbarLayout = 'static';
            if (a.opener) {
                if (a.opener.parents('.navbar-through').length > 0) navbarLayout = 'through';
                if (a.opener.parents('.navbar-fixed').length > 0) navbarLayout = 'fixed';
                noToolbar = a.opener.parents('.page').hasClass('no-toolbar') ? 'no-toolbar' : '';
                noNavbar  = a.opener.parents('.page').hasClass('no-navbar')  ? 'no-navbar'  : 'navbar-' + navbarLayout;
            }
            else if (view.container) {
                if ($(view.container).hasClass('navbar-through') || $(view.container).find('.navbar-through').length > 0) navbarLayout = 'through';
                if ($(view.container).hasClass('navbar-fixed') || $(view.container).find('.navbar-fixed').length > 0) navbarLayout = 'fixed';
                noToolbar = $(view.activePage.container).hasClass('no-toolbar') ? 'no-toolbar' : '';
                noNavbar  = $(view.activePage.container).hasClass('no-navbar')  ? 'no-navbar'  : 'navbar-' + navbarLayout;
            }
        }
        else {
            navbarLayout = 'fixed';
        }
        var searchbarHTML =
            '<form class="searchbar">' +
                '<div class="searchbar-input">' +
                    '<input type="search" placeholder="' + a.params.searchbarPlaceholderText + '">' +
                    '<a href="#" class="searchbar-clear"></a>' +
                '</div>' +
                (material ? '' : '<a href="#" class="searchbar-cancel">' + a.params.searchbarCancelText + '</a>') +
            '</form>' +
            '<div class="searchbar-overlay"></div>';
        var pageHTML =
            (navbarLayout === 'through' ? navbarHTML : '') +
            '<div class="pages">' +
                '<div data-page="' + pageName + '" class="page autocomplete-page ' + noNavbar + ' ' + noToolbar + '">' +
                    (navbarLayout === 'fixed' ? navbarHTML : '') +
                    searchbarHTML +
                    '<div class="page-content">' +
                        (navbarLayout === 'static' ? navbarHTML : '') +
                        '<div class="list-block autocomplete-found autocomplete-list-' + a.id + ' ' + (formTheme ? 'theme-' + formTheme : '') + '">' +
                            '<ul></ul>' +
                        '</div>' +
                        '<div class="list-block autocomplete-not-found">' +
                            '<ul><li class="item-content"><div class="item-inner"><div class="item-title">' + a.params.notFoundText + '</div></div></li></ul>' +
                        '</div>' +
                        '<div class="list-block autocomplete-values">' +
                            '<ul></ul>' +
                        '</div>' +
                    '</div>' +
                '</div>' +
            '</div>';
    }
    else {
        a.dropdownItemTemplate = t7.compile(a.params.dropdownItemTemplate ||
            '<li>' +
                '<label class="{{#unless placeholder}}label-radio{{/unless}} item-content" data-value="{{value}}">' +
                    '<div class="item-inner">' +
                        '<div class="item-title">{{text}}</div>' +
                    '</div>' +
                '</label>' +
            '</li>'
        );
        a.dropdownPlaceholderTemplate = t7.compile(a.params.dropdownPlaceholderTemplate ||
            '<li class="autocomplete-dropdown-placeholder">' +
                '<div class="item-content">' +
                    '<div class="item-inner">' +
                        '<div class="item-title">{{text}}</div>' +
                    '</div>' +
                '</label>' +
            '</li>'
        );
        a.dropdownTemplate = t7.compile(a.params.dropdownTemplate ||
            '<div class="autocomplete-dropdown">' +
                '<div class="autocomplete-dropdown-inner">' +
                    '<div class="list-block">' +
                        '<ul></ul>' +
                    '</div>' +
                '</div>' +
                '{{#if preloader}}' +
                '<div class="autocomplete-preloader preloader {{#if preloaderColor}}preloader-{{preloaderColor}}{{/if}}">{{#if material}}{{materialPreloaderHtml}}{{/if}}</div>' +
                '{{/if}}' +
            '</div>'
        );
    }

    // Define popup
    a.popup = undefined;

    // Define Dropdown
    a.dropdown = undefined;

    // Handle Input Value Change
    function handleInputValue (e) {
        var query = a.input.val();
        if (a.params.source) {
            a.params.source(a, query, function (items) {
                var itemsHTML = '';
                var limit = a.params.limit ? Math.min(a.params.limit, items.length) : items.length;
                a.items = items;
                var i, j;
                var regExp = new RegExp('('+query+')', 'i');
                for (i = 0; i < limit; i++) {
                    var itemValue = typeof items[i] === 'object' ? items[i][a.params.valueProperty] : items[i];
                    itemsHTML += a.dropdownItemTemplate({
                        value: itemValue,
                        text: (typeof items[i] !== 'object' ? items[i] : items[i][a.params.textProperty]).replace(regExp, '<b>$1</b>')
                    });
                }
                if (itemsHTML === '' && query === '' && a.params.dropdownPlaceholderText) {
                    itemsHTML += a.dropdownPlaceholderTemplate({
                        text: a.params.dropdownPlaceholderText,
                    });
                }
                a.dropdown.find('ul').html(itemsHTML);
            });
        }
    }
    // Handle Drop Down Click
    function handleDropdownClick (e) {
        /*jshint validthis:true */
        var clicked = $(this);
        var clickedItem;
        for (var i = 0; i < a.items.length; i++) {
            var itemValue = typeof a.items[i] === 'object' ? a.items[i][a.params.valueProperty] : a.items[i];
            var value = clicked.attr('data-value');
            if (itemValue === value || itemValue * 1 === value * 1) {
                clickedItem = a.items[i];
            }
        }
        if (a.params.updateInputValueOnSelect) {
            a.input.val(typeof clickedItem === 'object' ? clickedItem[a.params.textProperty] : clickedItem);
            a.input.trigger('input change');
        }

        if (a.params.onChange) {
            a.params.onChange(a, clickedItem);
        }

        a.close();
    }

    // Handle HTML Click to close Dropdown
    function closeOnHTMLClick (e) {
        var target = $(e.target);
        if (!(target.is(a.input[0]) || a.dropdown && target.parents(a.dropdown[0]).length > 0)) {
            a.close();
        }
    }

    a.positionDropDown = function () {
        var listBlock = a.input.parents('.list-block'),
            pageContent = a.input.parents('.page-content'),
            paddingTop = parseInt(pageContent.css('padding-top'), 10),
            paddingBottom = parseInt(pageContent.css('padding-top'), 10),
            // inputOffset = a.input.offset(),
            listBlockOffsetLeft = listBlock.length > 0 ? listBlock.offset().left - listBlock.parent().offset().left : 0,
            inputOffsetLeft = a.input.offset().left - (listBlock.length > 0 ? listBlock.offset().left : 0),
            inputOffsetTop = a.input.offset().top - (pageContent.offset().top - pageContent[0].scrollTop),
            maxHeight = pageContent[0].scrollHeight - paddingBottom - (inputOffsetTop + pageContent[0].scrollTop) - a.input[0].offsetHeight;

        a.dropdown.css({
            left: (listBlock.length > 0 ? listBlockOffsetLeft : inputOffsetLeft) + 'px',
            top: inputOffsetTop + pageContent[0].scrollTop + a.input[0].offsetHeight + 'px',
            width: (listBlock.length > 0 ? listBlock[0].offsetWidth : a.input[0].offsetWidth) + 'px'
        });
        a.dropdown.children('.autocomplete-dropdown-inner').css({
            maxHeight: maxHeight + 'px',
            paddingLeft: listBlock.length > 0 && !a.params.expandInput ? inputOffsetLeft - (material ? 16 : 15) + 'px' : ''
        });
    };

    // Event Listeners on new page
    a.pageInit = function (e) {
        var page = e.detail.page;
        a.page = $(page.container);
        a.pageData = page;
        if (page.name !== pageName) {
            return;
        }
        var container = $(page.container);
        // Init Search Bar
        var searchbar = app.searchbar(container.find('.searchbar'), {
            customSearch: true,
            onSearch: function (searchbar, data) {
                if (data.query.length === 0 && searchbar.active) {
                    searchbar.overlay.addClass('searchbar-overlay-active');
                }
                else {
                    searchbar.overlay.removeClass('searchbar-overlay-active');
                }

                var i, j, k;

                if (a.params.source) {
                    a.params.source(a, data.query, function(items) {
                        var itemsHTML = '';
                        var limit = a.params.limit ? Math.min(a.params.limit, items.length) : items.length;
                        a.items = items;
                        for (i = 0; i < limit; i++) {
                            var selected = false;
                            var itemValue = typeof items[i] === 'object' ? items[i][a.params.valueProperty] : items[i];
                            for (j = 0; j < a.value.length; j++) {
                                var aValue = typeof a.value[j] === 'object' ? a.value[j][a.params.valueProperty] : a.value[j];
                                if (aValue === itemValue || aValue * 1 === itemValue * 1) selected = true;
                            }
                            itemsHTML += a.itemTemplate({
                                value: itemValue,
                                text: typeof items[i] !== 'object' ? items[i] : items[i][a.params.textProperty],
                                inputType: a.inputType,
                                id: a.id,
                                inputName: a.inputName,
                                selected: selected,
                                checkbox: a.inputType === 'checkbox',
                                material: material
                            });
                        }
                        container.find('.autocomplete-found ul').html(itemsHTML);
                        if (items.length === 0) {
                            if (data.query.length !== 0) {
                                container.find('.autocomplete-not-found').show();
                                container.find('.autocomplete-found, .autocomplete-values').hide();
                            }
                            else {
                                container.find('.autocomplete-values').show();
                                container.find('.autocomplete-found, .autocomplete-not-found').hide();
                            }
                        }
                        else {
                            container.find('.autocomplete-found').show();
                            container.find('.autocomplete-not-found, .autocomplete-values').hide();
                        }
                    });
                }
            }
        });

        // Save searchbar instance
        a.searchbar = searchbar;

        // Update values
        function updateValues() {
            var valuesHTML = '';
            var i;
            for (i = 0; i < a.value.length; i++) {

                valuesHTML += a.itemTemplate({
                    value: typeof a.value[i] === 'object' ? a.value[i][a.params.valueProperty] : a.value[i],
                    text: typeof a.value[i] === 'object' ? a.value[i][a.params.textProperty]: a.value[i],
                    inputType: a.inputType,
                    id: a.id,
                    inputName: a.inputName + '-checked',
                    checkbox: a.inputType === 'checkbox',
                    material: material,
                    selected: true
                });
            }
            container.find('.autocomplete-values ul').html(valuesHTML);
        }

        // Handle Inputs
        container.on('change', 'input[type="radio"], input[type="checkbox"]', function () {
            var i;
            var input = this;
            var value = input.value;
            var text = $(input).parents('li').find('.item-title').text();
            var isValues = $(input).parents('.autocomplete-values').length > 0;
            var item, itemValue, aValue;
            if (isValues) {
                if (a.inputType === 'checkbox' && !input.checked) {
                    for (i = 0; i < a.value.length; i++) {
                        aValue = typeof a.value[i] === 'string' ? a.value[i] : a.value[i][a.params.valueProperty];
                        if (aValue === value || aValue * 1 === value * 1) {
                            a.value.splice(i, 1);
                        }
                    }
                    updateValues();
                    if (a.params.onChange) a.params.onChange(a, a.value);
                }
                return;
            }

            // Find Related Item
            for (i = 0; i < a.items.length; i++) {
                itemValue = typeof a.items[i] === 'string' ? a.items[i] : a.items[i][a.params.valueProperty];
                if (itemValue === value || itemValue * 1 === value * 1) item = a.items[i];
            }
            // Update Selected Value
            if (a.inputType === 'radio') {
                a.value = [item];
            }
            else {
                if (input.checked) {
                    a.value.push(item);
                }
                else {
                    for (i = 0; i < a.value.length; i++) {
                        aValue = typeof a.value[i] === 'string' ? a.value[i] : a.value[i][a.params.valueProperty];
                        if (aValue === value || aValue * 1 === value * 1) {
                            a.value.splice(i, 1);
                        }
                    }
                }
            }

            // Update Values Block
            updateValues();

            // On Select Callback
            if ((a.inputType === 'radio' && input.checked || a.inputType === 'checkbox') && a.params.onChange ) {
                a.params.onChange(a, a.value);
            }
            if (backOnSelect && a.inputType === 'radio') {
                if (a.params.openIn === 'popup') app.closeModal(a.popup);
                else view.router.back();
            }
        });

        // Update Values On Page Init
        updateValues();

        if (a.params.onOpen) a.params.onOpen(a);
    };

    // Show Hide Preloader
    a.showPreloader = function () {
        if (a.params.openIn === 'dropdown') {
            if (a.dropdown) a.dropdown.find('.autocomplete-preloader').addClass('autocomplete-preloader-visible');
        }
        else $('.autocomplete-preloader').addClass('autocomplete-preloader-visible');
    };

    a.hidePreloader = function () {
        if (a.params.openIn === 'dropdown') {
            if (a.dropdown) a.dropdown.find('.autocomplete-preloader').removeClass('autocomplete-preloader-visible');
        }
        else $('.autocomplete-preloader').removeClass('autocomplete-preloader-visible');
    };

    // Open Autocomplete Page/Popup
    a.open = function () {
        if (a.opened) return;
        a.opened = true;
        if (a.params.openIn === 'dropdown') {
            if (!a.dropdown) {
                a.dropdown = $(a.dropdownTemplate({
                    preloader: a.params.preloader,
                    preloaderColor: a.params.preloaderColor,
                    material: material,
                    materialPreloaderHtml: app.params.materialPreloaderHtml
                }));
                a.dropdown.on('click', 'label', handleDropdownClick);

            }
            var listBlock = a.input.parents('.list-block');
            if (listBlock.length && a.input.parents('.item-content').length > 0 && a.params.expandInput) {
                a.input.parents('.item-content').addClass('item-content-dropdown-expand');
            }
            a.positionDropDown();
            a.input.parents('.page-content').append(a.dropdown);
            a.dropdown.addClass('autocomplete-dropdown-in');
            a.input.trigger('input');
            $(window).on('resize', a.positionDropDown);
            if (a.params.onOpen) a.params.onOpen(a);
        }
        else {
            $(document).once('pageInit', '.autocomplete-page', a.pageInit);
            if (a.params.openIn === 'popup') {
                a.popup = app.popup(
                    '<div class="popup autocomplete-popup autocomplete-popup-' + a.inputName + '">' +
                        '<div class="view navbar-fixed">' +
                            pageHTML +
                        '</div>' +
                    '</div>'
                    );
                a.popup = $(a.popup);
                a.popup.once('closed', function () {
                    a.popup = undefined;
                    a.opened = false;
                    if (a.params.onClose) a.params.onClose(a);
                });
            }
            else {
                view.router.load({
                    content: pageHTML
                });
                $(document).once('pageBack', '.autocomplete-page', function () {
                    a.opened = false;
                    if (a.params.onClose) a.params.onClose(a);
                });
            }
        }
    };
    a.close = function (e) {
        if (!a.opened) return;
        if (a.params.openIn === 'dropdown') {
            if (e && e.type === 'blur' && a.dropdown.find('label.active-state').length > 0) return;
            a.dropdown.removeClass('autocomplete-dropdown-in').remove();
            a.input.parents('.item-content-dropdown-expand').removeClass('item-content-dropdown-expand');
            a.opened = false;
            $(window).off('resize', a.positionDropDown);
            if (a.params.onClose) a.params.onClose(a);
        }
        if (a.params.openIn === 'popup') {
            if (a.popup) app.closeModal(a.popup);
        }
    };

    // Init Events
    a.initEvents = function (detach) {
        var method = detach ? 'off' : 'on';
        if (a.params.openIn !== 'dropdown' && a.opener) {
            a.opener[method]('click', a.open);
        }
        if (a.params.openIn === 'dropdown' && a.input) {
            a.input[method]('focus', a.open);
            a.input[method]('input', handleInputValue);
            if (app.device.android) {
                $('html')[method]('click', closeOnHTMLClick);
            }
            else {
                a.input[method]('blur', a.close);
            }
        }
        if (detach && a.dropdown) {
            a.dropdown = null;
        }
    };

    // Init/Destroy Methods
    a.init = function () {
        a.initEvents();
    };
    a.destroy = function () {
        a.initEvents(true);
        a = null;
    };

    // Init
    a.init();

    return a;
};
app.autocomplete = function (params) {
    return new Autocomplete(params);
};