(function () {
	
	function hashToObject(hash) {
		var _removeHash = function (input) {
			if (input.indexOf("#/") > -1) {
				input = input.substring(input.indexOf("#/") + 2);
			} else if (input.indexOf("#") > -1) {
				input = input.substring(1);
			}
			return input;
		};
	
		var _deserialize = function (input) {
			var match,
				pl = /\+/g,  // Regex for replacing addition symbol with a space
				search = /([^&=]+)=?([^&]*)/g,
				decode = function (s) {
					return decodeURIComponent(s.replace(pl, " "));
				},
				obj = {};
			match = search.exec(input);
			while (match) {
				obj[decode(match[1])] = decode(match[2]);
				match = search.exec(input);
			}
	
			return obj;
		};
	
		return _deserialize(_removeHash(hash));
	};

	function handleNoOpener() {
		console.error('Unable to communicate back to main frame! Auth may have succeeded but we are unable to provide token to the app. In IE, this may be due to bad security zone configurations');
		var errorCodeId = "80061210";
		var helpLink = 'http://go.microsoft.com/fwlink/?LinkID=398563&client=MailApp&error=Microsoft.Crm.Exception:' + errorCodeId;
		
		var supportedLanguages = [
			"ar-sa","bg-bg", "ca-es",
			"zh-tw", "cs-cz", "da-dk",
			"de-de", "el-gr", "fi-fi",
			"fr-fr", "he-il", "hu-hu",
			"it-it", "ja-jp", "ko-kr",
			"nl-nl", "nb-no", "pl-pl",
			"pt-br", "ro-ro", "ru-ru",
			"hr-hr", "sk-sk", "sv-se",
			"th-th", "tr-tr", "id-id",
			"uk-ua", "sl-si", "et-ee",
			"lv-lv", "lt-lt", "vi-vn",
			"eu-es", "hi-in", "ms-my",
			"kk-kz", "gl-es", "zh-cn",
			"pt-pt", "sr-latn-rs", "zh-hk",
			"es-es", "sr-cyrl-rs",
		];

		function getDisplayLanguage()
		{
			const displayLanguage = localStorage && localStorage.getItem('MailApp_DisplayLanguage');

			if (displayLanguage && supportedLanguages.indexOf(displayLanguage.toLowerCase()) !== -1)
			{
				return displayLanguage;
			}

			return null;
		}

		var resourceId = getDisplayLanguage();

		// Request resources in order to show error message
		var resourceUrl =
			window.location.protocol +
			'//' +
			window.location.host +
			'/crmmailapp/resources/loc/resources' +
			(resourceId ? '.' + resourceId : '') +
			'.js';

		var req = new XMLHttpRequest();
		req.onload = function(evt) {
			// Load resources into execution context
			var resourceJs = req.response;
			eval(resourceJs); //CodeQL [SM01632] By design as resoruces js object generated will not be a trival fix.

			if (RESOURCES) {
				var messageContainer = document.getElementById('messageContainer');
				var messageElement = document.getElementById('messageText');
				var linkElement = document.getElementById('messageLink');

				messageContainer.className = '';
				linkElement.href = helpLink;
				linkElement.innerText = RESOURCES['MoCA_OWA_Help_Link_Text'];
				messageElement.innerText = RESOURCES['Error_Message_0x' + errorCodeId];
			} else {
				console.error('Could not successfully load resources');
			}
		}
		req.open('GET', resourceUrl);
		req.send();
	};

	function communicateOfficeDialog()
	{
		Office.initialize = function ()
		{
			try
			{
				updateResponseObjectWithCallbackType(CALLBACK_TYPE.OFFICE_MESSAGE_PARENT);

				Office.context.ui.messageParent(JSON.stringify(responseObject), {targetOrigin: window.location.origin});
			}
			catch(error)
			{
				return communicateParentWindow(CALLBACK_TYPE.WINDOW_OPENER_OFFICE_FAILED);
			}

			window.setTimeout(function()
			{
				communicateParentWindow(CALLBACK_TYPE.WINDOW_OPENER_OFFICE_TIMEOUT);
			}, 1500);
		};
	}

	function communicateParentWindow(callbackType)
	{
		updateResponseObjectWithCallbackType(callbackType);
		
		try
		{
			// We are in our own window. Need to communicate with main page.
			window.opener.msalLoginCallback(responseObject);
			window.close();
		}
		catch (err)
		{
			handleNoOpener();
		}
	}

	function updateResponseObjectWithCallbackType(callbackType)
	{
		responseObject.callback_type = (responseObject.error_code ? "failure:": "success:") + callbackType;
	}

	var CALLBACK_TYPE = {
		OFFICE_MESSAGE_PARENT: "office_message_parent",
		WINDOW_PARENT: "window_parent_silent_flow",
		WINDOW_OPENER: "window_opener",
		WINDOW_OPENER_OFFICE_FAILED: "window_opener_office_failed",
		WINDOW_OPENER_OFFICE_TIMEOUT: "window_opener_office_timeout",
	};

	var hashParams = hashToObject(window.location.hash);
	var responseObject = { access_token: hashParams.access_token, error_code: hashParams.error_code, callback_type: "" };

	// silent renew flow through iFrame
	if (window.parent && window.parent.msalLoginCallback)
	{
		updateResponseObjectWithCallbackType(CALLBACK_TYPE.WINDOW_PARENT);

		window.parent.msalLoginCallback(responseObject);
	}
	// user interaction flow
	else
	{
		var loginDialogMode = "";
		
		try
		{
			loginDialogMode = localStorage.getItem("MailApp_LoginDialogMode");
			localStorage.setItem("MailApp_LoginDialogMode", "");
		}
		catch(e) {}
		
		if (loginDialogMode === "OfficeDialog")
		{
			communicateOfficeDialog();
		}
		else 
		{
			communicateParentWindow(CALLBACK_TYPE.WINDOW_OPENER);
		}
	}
})();