(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery', 'jquery.mobile', 'backbone', 'marionette', 'utilities'], factory);
    } else {
        factory(jQuery);
    }
}(function($) {

    var utilities = {},
        headerHeight,
        footerHeight,
        subHeaderHeight;

    utilities.flattenLinks = function (object) {
        var links = object.get('link');
        if (typeof links !== 'undefined') {
            for (var i = 0, size = links.length; i < size; i++) {
                if (links[i].title) {
                    object.set(links[i].title, links[i]);
                } else {
                    object.set('self', links[i]);
                }
            }
            object.unset('link');
        }
    };

    utilities.globalInit = function (app) {
        if (app.user) {
            if (!app.provider) {
                utilities.checkROA(app);
            }
            utilities.resizePanes();
            $(window).resize(utilities.resizePanes);
        }

        $('body').on('pageshow', function (event, ui) {
            var prevPage = $(ui.prevPage);
            if (prevPage.hasClass('ui-dialog')) {
                prevPage.remove();
            }

            utilities.resizePanes(app.customHeight || 0);
            utilities.registerLoadingSpinner(app.spinnerOptions || 0);
        });
    };

    utilities.logout = function(config){
        config = config || {};
        require(['UserSession', 'Resources', 'AppointmentRequest'],
            function(UserSession, resources, AppointmentRequest){

	            AppointmentRequest.clearInstance({
		            success: function () {
			            var mhpuser = UserSession.instance().get('mhpuser');

			            if (typeof mhpuser !== "undefined") {
				            var logoutUrl = resources.get('logout').get('href');
				            $.ajax({
					            url: resources.get('token').get('href'),
					            type: 'DELETE',
					            success: function(data){
						            utilities.cleanUpSession();
						            if(!config.preventLogoutLocation){
							            window.location = logoutUrl;
						            }
					            }
				            });
			            }
		            }
	            });
            }
        );
    };

    utilities.login = function(){
        window.location = utilities.getReferencePath() + '../PatientViewerServices/oauthlogin?redirect_uri=' + utilities.getReferencePathWithHash();
    }

    utilities.launchpad = function(){
        function getLaunchpadPath(){
            var self = this,
                loc = window.location,
                path = loc.protocol + "//" + loc.hostname + (loc.port ? ":" + loc.port : loc.port ),
                launchpadPath = '/launchpad';

            if (loc.hostname === 'localhost' && loc.port !== '8080'){
                path = path + ":8080";
            }
            return path+launchpadPath;
        }
        utilities.launchpadPath = utilities.launchpadPath || getLaunchpadPath();
        window.location = utilities.launchpadPath;
    };

    utilities.clearLeftPanel = function () {
        "use strict";
        var $leftPanel = $('.ui-panel-position-left.ui-panel-open');

        if ($leftPanel.length) {
            $('#content-secondary').toggleClass('hidden');
            $('#content-primary').toggleClass('no-float');
            $leftPanel.panel('toggle');
        }
    };

    utilities.slidePrimary = function (selector) {
        var $moveContent = $(selector || '#content-primary');
        if ($moveContent.hasClass('closed')) {
            $moveContent.removeAttr('style').toggleClass('closed');
        } else {
            $moveContent.animate({
                left: '0'
            }, 300, function () {
                $moveContent.addClass('closed');
            });
        }
    };

    utilities.resizePanes = function () {
        headerHeight = $('#header').outerHeight();
        footerHeight = $('#footer').outerHeight();
        subHeaderHeight = $('#sub-header').outerHeight();
        //header and footer have lost relevence in soc
        $('#main .scrollable').outerHeight($(window).outerHeight() - headerHeight - subHeaderHeight - footerHeight);
        utilities.eventAggregator.trigger('footer');
    };

    utilities.checkROA = function (app) {
        var rightOfAccessAccepted = true;
        if (typeof app.user !== 'undefined' && app.user.id) {
            rightOfAccessAccepted = typeof app.user.rightOfAccessAccepted !== 'undefined' ? app.user.rightOfAccessAccepted : app.user.attributes.rightOfAccessAccepted;
            if (!rightOfAccessAccepted) {
                window.location = utilities.getReferencePath() + '../roa/index.html?url=' + window.location.pathname;
                ;
            }
        }
    };

    utilities.removeFromStorage = function (key) {
        if (key) {
            try {
                window.localStorage.removeItem(key);
            } catch (e) {
                if (e == QUOTA_EXCEEDED_ERR) {
                    var message = 'Local-Storage Quota exceeded!';
                    if (window.console && window.console.log) {
                        console.log(message);
                    } else {
                        alert(message);
                    }
                }
            }
        }
    };

    utilities.writeToStorage = function (key, value) {
        if (!value) {
            value = null;
        }

        try {
            window.localStorage[key] = JSON.stringify(value);
        } catch (e) {
            if (e == QUOTA_EXCEEDED_ERR) {
                var message = 'Local-Storage Quota exceeded!';
                if (window.console && window.console.log) {
                    console.log(message);
                } else {
                    alert(message);
                }
            }
        }
    };

    utilities.readFromStorage = function (key) {
        var value = null;
        if (typeof(window.localStorage) != 'undefined') {
            value = JSON.parse(window.localStorage[key] || null);
        }
        return value;
    };

    utilities.checkEULA = function (prevHash, modifiedDate) {
        var url = window.location.pathname,
            value = utilities.readFromStorage(url + "eula");
        if (value === null || new Date(modifiedDate).getTime() > value.dateAccepted) {
            return "#eula";
        } else {
            return prevHash;
        }
    };

    utilities.getReferencePath = function () {
        var referencePath = window.location.protocol + "//" + window.location.host + window.location.pathname;
        var index = referencePath.indexOf("index.html");
        if (index !== -1) {
            referencePath = referencePath.substring(0, index);
        }
        return referencePath;
    };

    //Get the path to PatientViewerServices
    utilities.getMhpReferencePath = function () {
        var referencePath = window.location.protocol + "//" + window.location.host + "/PatientViewerServices";
        return referencePath;
    };

    utilities.getReferencePathWithHash = function () {
        return encodeURI(utilities.getReferencePath() + window.location.hash);
    };

    utilities.deleteCookie = function (cookieName) {
        document.cookie = encodeURIComponent(cookieName) + "=deleted; expires=" + new Date(0).toUTCString();
    };

    utilities.cleanUpSession = function () {
        window.sessionStorage['token'] = null;
        $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
            jqXHR.setRequestHeader("Authorization", "");
        });
        utilities.deleteCookie('JSESSIONID');
    };

    utilities.findMessage = function (errMsg) {
        var lines = errMsg.split('\n');

        for (var i = 0; i < lines.length; i++) {
            if (lines[i].indexOf('Message:') >= 0) {
                return lines[i];
            }
        }
        return errMsg;
    };

    utilities.parseTokenAndRegisterOauthHandler = function () {
        var params = {}, queryString = location.search.substring(1),
            regex = /([^&=]+)=([^&]*)/g, m;
        while (m = regex.exec(queryString)) {
            params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
        }

        var token = params['token'];

        if (typeof token !== 'undefined' && token !== 'undefined' && token !== null && token !== 'null') {
            window.sessionStorage['token'] = JSON.stringify(token);
        }

        var storedToken = window.sessionStorage['token'];

        if (typeof storedToken !== 'undefined' && storedToken !== 'undefined' && storedToken !== null && storedToken !== 'null') {
            $.ajaxPrefilter(function (options, originalOptions, jqXHR) {
                var currentToken = JSON.parse(storedToken);
                jqXHR.setRequestHeader("Authorization", "Bearer " + currentToken);
            });
        } else {
            utilities.cleanUpSession();
        }

        $(document).ajaxError(function (e, jqxhr, settings, exception) {
            if (jqxhr.status == 0 || jqxhr.status == 200 || jqxhr.status == 400 || jqxhr.status == 404) {

            } else if (jqxhr.status == 403) {
                utilities.cleanUpSession();
                window.location = utilities.getReferencePath() + '../PatientViewerServices/oauthlogin?redirect_uri=' + utilities.getReferencePathWithHash();
            } else if (jqxhr.status == 401) {
                if (jqxhr.responseText.indexOf('invalid_token') > 0) {
                    utilities.cleanUpSession();
                    $.ajax(settings);
                }
            }
        });

    };
    utilities.parseTokenAndRegisterOauthHandler();

    utilities.setGlobalAjaxConfig = function(){
        $.ajaxSetup({
            cache: false
        });
    };
    utilities.setGlobalAjaxConfig();

    utilities.registerLoadingSpinner = function (options) {
        $(document)
            .ajaxStart(function (event, xhr, settings) {
                $.mobile.loading('show', options || 0);
                $('.ui-loader').css('display', 'block');
                $('#dialog-screen').removeClass('hidden');
            })
            .ajaxStop(function () {
                $.mobile.loading('hide');
                $('.ui-loader').removeAttr('style');
                $('#dialog-screen').addClass('hidden');
            })
            .ajaxError(function () {
                $.mobile.loading('hide');
                $('.ui-loader').removeAttr('style');
                $('#dialog-screen').addClass('hidden');
            });
    };

    utilities.create = function (page) {
        try {
            page.page("destroy");
        } catch (err) {
            // if page has not been initialized yet, destroy is not necessary
        }
        page.page();
    };

    utilities.eventAggregator = _.extend({}, Backbone.Events);
    utilities.eventAggregator.on("logout", function () {
        utilities.cleanUpSession();
    });

    return {
        getUtilities: function () {
            return utilities;
        }
    };

}));