; (function (trv, $, window, document, undefined) {
    "use strict";
    
    var utils = trv.utils;
    if (!utils) {
        throw 'Missing telerikReportViewer.utils';
    }

    if (!trv.ServiceClient) {
        throw "Missing telerikReportViewer.ServiceClient";
    }
    
    if (!trv.ReportViewerController) {
        throw "Missing telerikReportViewer.ReportViewerController";
    }

    if (!trv.HistoryManager) {
        throw "Missing telerikReportViewer.HistoryManager";
    }
    
    var binder = trv.binder;
    if (!binder) {
        throw "Missing telerikReportViewer.Binder";
    }

    var toolsModel = trv.toolsModel;
    if (!toolsModel) {
        throw "Missing telerikReportViewer.toolsModel";
    }
    
    var toolsController = trv.toolsController;
    if (!toolsController) {
        throw "Missing telerikReportViewer.toolsController";
    }
    
    var defaultOptions = {

    };
    
    function reportViewer(dom, options) {
        options = jQuery.extend({}, defaultOptions, options);
        
        if (!options.templateUrl) {
            throw "ReportViewer template is missing. Please specify the templateUrl in the options.";
        }

        var $placeholder = $(dom);

        var client = new trv.ServiceClient({ address: options.serviceUrl });
        var controller = new trv.ReportViewerController({ serviceClient: client });
        var history = new trv.HistoryManager({ controller: controller });
        var model = new toolsModel({ controller: controller, history: history });

        toolsController({ controller: controller, history: history, model: model });
        
        var viewer = {};

        $.extend(
            viewer,
            {
                refreshReport: function () {
                    controller.refreshReport();
                    return viewer;
                },

                reportSource: function (rs) {
                    if (rs) {
                        controller.reportSource(rs);
                        return viewer;
                    } 
                    
                    return controller.reportSource();
                }
            }
        );
        
        function init() {
            binder
                .bind($placeholder, { controller: controller, history: history, model: model });

            new trv.PerspectiveManager(dom, controller)
                .attach();
            
            start();
        }
        
        function start() {
            if (options.viewMode) {
                controller.viewMode(options.viewMode);
            }

            if ('scaleMode' in options || 'scale' in options) {
                controller.scale(options);
            }

            if (options.reportSource) {
                controller.reportSource(options.reportSource);
            }
        }

        // last!
        $placeholder.load(options.templateUrl, function (data, status, xhr) {
            if (status == "error") {
                $placeholder.html(xhr.responseText);
            } else {
                init();
                if (typeof options.ready == "function") {
                    options.ready.call(viewer);
                }
            }
        });

        return viewer;
    };

    var pluginName = "telerik_ReportViewer";

    jQuery.fn[pluginName] = function (options) {
        return this.each(function () {
            if (!$.data(this, pluginName)) {
                $.data(this, pluginName, new reportViewer(this, options));
            }
        });
    };

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