// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define(['hp/services/IndexService',
        'hp/services/IndexFilter',
        'jquery'],
function(indexService, IndexFilter) { "use strict";

    var SelectionValidator = (function() {

        var CANCEL     = 'cancel',  // Used by caller to cancel the process
            RUNNING    = 'running', // Maintain by this object 
            READY      = 'ready';   // Validator is ready to run

        /**
         * Constructor
         */
        function SelectionValidator() {
            var self = this;
            var selection = null;
            var uris = [];
            var filter = null;
            var resource = null;
            var selectionCount = 0;
            var state = null;
            var handlers = null;

            function reset() {
                state = READY;
            }

            function handleSuccess() {
                if (state === RUNNING) {
                    reset();
                    if (handlers) {
                        handlers.success(self);
                    }
                }
            }

            function onError(errorInfo) {
                if (state === RUNNING) {
                    reset();
                    if (handlers) {
                        handlers.error(self);
                    }
                }
            }

            function onSuccess(result) {
                if (result.total >= selectionCount) {
                    handleSuccess();
                } else {
                    onError();
                }
            }

            function isEqual(selection1, selection2) {
                var curis = selection1.uris;
                var suris = selection2.uris;
                return $(curis).not(suris).length === 0 && $(suris).not(curis).length === 0;
            }

            /**
             * Return the current selection which this object is validating
             * @return {selection} selection object
             */
            this.getSelection = function() {
                return selection;
            };

            /**
             * Return the current filter which this object uses to validate the selection
             * @return {IndexFilter} IndexFilter object
             */
            this.getFilter = function() {
                return filter;
            };

            /**
             * Check to see if this instance is operating on the current selection and filter.
             * It is considered current if both of the following conditions are met:
             * 1 - the set of uris are the same in the selections
             * 2 - the filter's user queries are the same.
             * 
             * @param {curSelection}  The current selection object
             * @param {curFilter}  The current IndexFilter object
             * @return boolean if the comparison is successful; false otherwise.
             */
            this.isCurrent = function(curSelection, curFilter) {
                // TODO: Consider moving this function to Resource when this class is
                //       wired together with Resource along with ResourceSelection
                var result = false;
                var thisFilter = null;                
                
                thisFilter = new IndexFilter(filter);
                thisFilter.unsetProperty('_uri');
                
                result = isEqual(curSelection, selection) &&
                    thisFilter.getUserQuery() === curFilter.getUserQuery();
                
                return result;
            };

            /**
             * Set the state of this object to "CANCEL". In effect, the validation
             * results are ignored and callback handlers will not be called. 
             */
            this.cancel = function () {
                state = CANCEL;
            };

            /**
             * Validate the selection maintained by this object is valid. It is valid
             * if all uris in the selection exist in the index service. The success
             * handler is called if validation passes and error handler is called if
             * validation fails. Both handlers are called with this validator instance
             * as parameter.
             * 
             * @param {callbacks} handlers {success:function(validator), error:function(validator)}
             */
            this.validate = function(callbacks) {
                if (selection && (state === READY)) {
                    state = RUNNING;
                    handlers = callbacks;
                    selectionCount = selection.uris.length;
                    $.extend(uris, selection.uris);
                    resource.existsInFilter(uris, filter, {
                        success: onSuccess,
                        error: onError
                    });
                }
            };

            this.init = function(arg) {
                if (arg) {
                    filter = arg.filter;
                    selection = arg.selection;
                    resource = arg.resource;
                }
                reset();
            };
        }

        return SelectionValidator;
    }());
    return SelectionValidator;
});