// --
// Copyright (C) 2001-2017 OTRS AG, http://otrs.com/
// --
// This software comes with ABSOLUTELY NO WARRANTY. For details, see
// the enclosed file COPYING for license information (AGPL). If you
// did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
// --

"use strict";

var Core = Core || {};
Core.UI = Core.UI || {};

/**
 * @namespace
 * @exports TargetNS as Core.UI.Autocomplete
 * @description
 *      This namespace contains autocomplete specific functions.
 */
Core.UI.Autocomplete = (function (TargetNS) {
    var ConfigFallback = {
            AutoCompleteActive: 1,
            MinQueryLength: 2,
            QueryDelay: 100,
            MaxResultsDisplayed: 20
        },
        ConfigElements = ['AutoCompleteActive', 'MinQueryLength', 'QueryDelay', 'MaxResultsDisplayed', 'ButtonText'],
        Config = {},
        AJAXLoaderPrefix = 'AJAXLoader';

    function InitConfig(Type, Options) {
        var TypeConfig = Core.Config.Get('Autocomplete');

        $.each(ConfigElements, function (ConfigKey, ConfigElement) {
            // Option, Type, Fallback
            if (Options && typeof Options[ConfigElement] !== 'undefined') {
                Config[ConfigElement] = Options[ConfigElement];
            }
            else if (Type && TypeConfig[Type]) {
                Config[ConfigElement] = TypeConfig[Type][ConfigElement];
            }
            else {
                Config[ConfigElement] = ConfigFallback[ConfigElement];
            }
        });

        // make sure, that the value of AutoCompleteActive is casted to int
        Config.AutoCompleteActive = parseInt(Config.AutoCompleteActive, 10);

        // if button should be shown, set minlength to an unreachable value
        if (!Config.AutoCompleteActive) {
            Config.MinQueryLength = 500;
        }

        return Config;
    }

    TargetNS.GetConfig = function(Key) {
        return Config[Key];
    };

    // Needed for the handling of searches with ActiveAutoComplete = 0
    TargetNS.SearchButtonClicked = {};

    /**
     * @function
     * @description
     *      This function initializes autocomplete on an input element.
     * @param {jQueryObject} $Element which gets autocomplete infos.
     * @param {Function} SourceFunction defines the source data for the autocomplete
     *              Two params: Request and Response
     *                      Request: the data provided by the autocomplete (e.g. the entered text)
     *                      Response: the function defined by the autocomplete to call with the selected data
     * @param {Function} SelectFunction is executed, if an entry is selected
     *              Two params: Event and UI
     *                      Event: the original browser event object
     *                      UI: the data given from the UI (e.g. UI.item is the selected autocomplete list item)
     * @param {String} Type of autocompletion, e.g. "CustomerSearch" etc.
     * @param {Object} Options object data with autocomplete plugin options
     * @return nothing
     */
    TargetNS.Init = function ($Element, SourceFunction, SelectFunction, Type, Options) {
        var Config,
            $Loader;

        // Only start autocompletion, if $Element is valid element
        if (!isJQueryObject($Element) || !$Element.length) {
            return;
        }

        Config = InitConfig(Type, Options);

        $Element.each(function () {
            var $SingleElement = $(this);
            $SingleElement.autocomplete({
                minLength: Config.MinQueryLength,
                delay: Config.QueryDelay,
                search: function() {
                    var FieldID = $SingleElement.attr('id'),
                        LoaderHTML = '<span id="' + AJAXLoaderPrefix + FieldID + '" class="AJAXLoader"></span>';

                    $Loader = $('#' + AJAXLoaderPrefix + FieldID);

                    if (!$Loader.length) {
                        $SingleElement.after(LoaderHTML);
                        $Loader = $('#' + AJAXLoaderPrefix + FieldID);
                    }
                    else {
                        $Loader.show();
                    }
                },
                response: function() {
                    // remove loader again
                    $Loader.hide();
                },
                open: function() {
                    // force a higher z-index than the overlay/dialog
                    $SingleElement.autocomplete('widget').addClass('ui-overlay-autocomplete');
                    return false;
                },
                source: function (Request, Response) {
                    // if an old ajax request is already running, stop the old request and start the new one
                    if ($SingleElement.data('AutoCompleteXHR')) {
                        $SingleElement.data('AutoCompleteXHR').abort();
                        $SingleElement.removeData('AutoCompleteXHR');
                        // run the response function to hide the request animation
                        Response({});
                    }

                    if (SourceFunction) {
                        SourceFunction(Request, Response);
                    }

                    /*
                     * Your SourceFunction must return an array of the data you collected.
                     * Every array element is an object with the following keys:
                     * label: the string displayed in the suggestion menu
                     * value: the string to be inserted in the input field
                     * You can add more keys, if you want to transport data to the select function
                     * all keys will be available there via the UI.item object.
                     *
                     * If you use an ajax function inside your source, make sure to
                     * save the XHRObject in a data-value, to control the xhr automatically:
                     * $Element.data('AutoCompleteXHR', YourCallHere());
                     * This makes sure, that we can abort old ajax request, if new searches are triggered.
                     *
                     * The input value can be found in Request.term. Don't forget to send the MaxResult config
                     * to the server in your ajax request.
                     */
                },
                select: function (Event, UI) {
                    if (SelectFunction) {
                        SelectFunction(Event, UI);
                    }

                    Event.preventDefault();
                    return false;
                }
            });
        });

        if (!Config.AutoCompleteActive) {
            $Element.each(function () {
                var $SelectedElement = $(this);
                $SelectedElement.after('<button id="' + Core.App.EscapeSelector($SelectedElement.attr('id')) + 'Search" type="button">' + Config.ButtonText + '</button>');
                $('#' + Core.App.EscapeSelector($SelectedElement.attr('id')) + 'Search').click(function () {
                    TargetNS.SearchButtonClicked[$SelectedElement.attr('id')] = true;
                    $SelectedElement.autocomplete("option", "minLength", 0);
                    $SelectedElement.autocomplete("search");
                    $SelectedElement.autocomplete("option", "minLength", 500);
                });
            });
        }
    };

    return TargetNS;
}(Core.UI.Autocomplete || {}));
