; (function (trv, $, window, document, undefined) {
    "use strict";
    
    trv.HistoryManager = function (options) {
        var controller = options.controller;
        if (!controller) {
            throw "No controller (telerikReporting.reportViewerController) has been specified.";
        }

        var history = [],
            position = -1      
        ;

        controller
            .beforeLoadReport(function () {
                addToHistory();
            });
        
        function addToHistory() {
            var current;
            if (history.length) {
                current = history[position];
            }
            var rs = controller.reportSource();
            if (!reportSourcesAreEqual(current, rs)) {
                history = Array.prototype.slice.call(history, 0, position + 1);
                history.push(rs);
                position = history.length - 1;
            }            
        }

        function exec(rs) {
            controller.reportSource(rs);
            controller.refreshReport();
        }

        function canMove(step) {
            var newPos = position + step;
            return (0 <= newPos && newPos < history.length);
        }

        function move(step) {
            var newPos = position + step;
            if (newPos < 0) {
                newPos = 0;
            }
            else if (newPos >= history.length) {
                newPos = history.length - 1;
            }

            if (newPos != position) {
                position = newPos;
                exec(history[position]);
            }
        }

        return {
            back: function () {
                move(-1);
            },

            forward: function () {
                move(+1);
            },

            canMoveBack: function () {
                return canMove(-1);
            },

            canMoveForward: function () {
                return canMove(1);
            },
        };
    };
    
    function reportSourcesAreEqual(rs1, rs2) {
        if (rs1 && rs2 && rs1.report === rs2.report) {
            var params1 = [], params2 = [];

            if (rs1.parameters)
                params1 = Object.getOwnPropertyNames(rs1.parameters);

            if (rs2.parameters)
                params2 = Object.getOwnPropertyNames(rs2.parameters);

            if (params1.length == params2.length) {
                for (var i = params1.length - 1; i >= 0; i--) {
                    var p = params1[i];
                    var v1 = rs1.parameters[p];
                    var v2 = rs2.parameters[p];

                    if (Array.isArray(v1)) {
                        if (!Array.isArray(v2))
                            return false;

                        if (v1.length != v2.length)
                            return false;

                        for (var j = v1.length - 1; j >= 0; j--) {
                            if (v1[j] !== v2[j])
                                return false;
                        }
                    }
                    else if (v1 !== v2) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }

}(window.telerikReportViewer = window.telerikReportViewer || {}, jQuery, window, document));