/*
 *+------------------------------------------------------------------------+
 *| Licensed Materials - Property of IBM
 *| IBM Cognos Products: BI Content Explorer
 *| (C) Copyright IBM Corp. 2015, 2019
 *|
 *| US Government Users Restricted Rights - Use, duplication or disclosure
 *| restricted by GSA ADP Schedule Contract with IBM Corp.
 *+------------------------------------------------------------------------+
 */

define([
	'bi/glass/app/ContentView',
	'./nls/StringResource',
	'jquery',
	'underscore',
	'doT',
	'text!./templates/QRSlideoutViewTemplate.html',
	'./lib/qrcode/build/qrcode'
], function (ContentView, StringResource, $, _, dot, CAMobileTemplate, QRCode) {
	'use strict';

	var QRSlideoutView = ContentView.extend({
		init: function(options) {
			QRSlideoutView.inherited('init', this, arguments);
			_.extend(this, options);
			this.$el.addClass('caMobilePaneContainer');
		},

		open: function(context, options) {
			this.glassContext = __glassAppController.glassContext; // eslint-disable-line no-undef
			this.options = options;
			this.render();

			return Promise.resolve();
		},

		generateSlideout: function () {
			return dot.template(CAMobileTemplate)({
				'strings': {
					'getMobileApp': StringResource.get('getMobileApp').toUpperCase(),
					'cognosAnalytics': StringResource.get('cognosAnalytics'),
					'downloadMobileApp': StringResource.get('downloadMobileApp'),
					'genQRCode': StringResource.get('genQRCode'),
					'mobileTwoFactor': StringResource.get('mobileTwoFactor'),
					'learnMore': StringResource.get('learnMore'),
					'appIos': StringResource.get('appIos'),
					'appAndroid': StringResource.get('appAndroid'),
					'appUseMessage': StringResource.get('appUseMessage').toUpperCase(),
					'getAppMessage': StringResource.get('getAppMessage'),
					'appIcon': this.options.appIcon
				}
			});
		},

		addEventListeners: function () {
			$('#mobileGenQR').click(this.onGenerateQRClick.bind(this));
			$('.mobileTwoFactorMessage').click(this.onSecondFactorClick.bind(this));
		},

		/**
		* Render the mobile app property page view.
		*/
		render: function() {
			var slideoutHtml = this.generateSlideout();
			this.$el.append(slideoutHtml);
			this.addEventListeners();

			return Promise.resolve(this.$el);
		},

		formatSecondFactorCountdownTime: function(startTime, expirationTime) {
			const differenceInTime = expirationTime - startTime;
			const minutes = Math.floor((differenceInTime % (1000 * 60 * 60)) / (1000 * 60));
			const seconds = Math.floor((differenceInTime % (1000 * 60)) / 1000);

			const timeAsString = this.padTimeNumber(minutes) + ':' + this.padTimeNumber(seconds);
			return timeAsString;
		},

		padTimeNumber: function(number) {
			number = String(number);
			while (number.length < 2) {number = '0' + number;}
			return number;
		},

		setCountdownInterval: function(secondFactor) {
			const displayElement = $('.mobileQRTwoFactorTimer');
			const finalTime = Date.parse(secondFactor.expires);

			var now;
			var timer = setInterval(function() {
				now = new Date().getTime();

				var differenceInTime = finalTime - now;
				displayElement.html(this.formatSecondFactorCountdownTime(now, finalTime));
				if (differenceInTime < 0) {
					clearInterval(timer);
					displayElement.html(StringResource.get('tokenExpired'));
				}
			}.bind(this), 1000);
		},

		generateQR: function (deepLink) {
			QRCode.toCanvas(document.getElementById('mobileQRCodeCanvas'), deepLink, function(err) {
				if(err) console.log(err);
			});

			this.hideGenerateQRDialog();
		},

		hideGenerateQRDialog: function () {
			$('#mobileQRCodeCanvas').style = 'width: 200px; height: 200px';
			$('#mobileGenQR').addClass('hidden');
		},

		displayTwoFactor: function (secondFactor) {
			const startTime = new Date().getTime();
			const expirationTime = Date.parse(secondFactor.expires);
			$('.mobileQRTwoFactor').removeClass('hidden');
			$('.mobileQRTwoFactorPin').html(secondFactor.value);
			$('.mobileQRTwoFactorTimer').html(this.formatSecondFactorCountdownTime(startTime, expirationTime));
		},

		/**
		* Generates a QR code and places it into the QRCodeCanvas element
		*/
		onGenerateQRClick: function() {
			this.retrieveLoginToken().then(function(response) {
				const secondFactor = response.secondFactor;
				const deepLink = this.formatDeepLink(response);

				this.generateQR(deepLink);
				this.displayTwoFactor(secondFactor);

				this.setCountdownInterval(secondFactor);
			}.bind(this)).catch(function() {
				const deepLink = this.formatDeepLink();
				this.generateQR(deepLink);
			}.bind(this));
		},

		/**
		* Takes in the JSON response of v1/loginToken and outputs a deeplink to the app
		* Also removes the second factor from the response
		*/
		formatDeepLink: function(response) {
			// Save the secondFactor locally and remove it from the json
			var deepLink = `camobile://?serverUrl=${encodeURIComponent(this.getServerURL())}`;

			if(response) {
				deepLink = deepLink +
					`&loginToken=${encodeURIComponent(JSON.stringify(response.loginToken))}` +
					`&x-ca-affinity=${encodeURIComponent(response.affinityHeader)}`;
			}
			return deepLink;
		},

		/**
		* Displays the second factor and sets a countdown
		*/
		onSecondFactorClick: function() {
			if(!this.secondFactor) {
				return false;
			}
			$('.mobileTwoFactorPin').html(this.secondFactor.value);
			$('.mobileTwoFactor').removeClass('hidden');
			var expirationDate = Date.parse(this.secondFactor.expires);
			var now = new Date().getTime();
			$('.mobileTwoFactorTimer').html(this.formatSecondFactorCountdownTime(now, expirationDate));

			this._createCountdownInterval($('.mobileTwoFactorTimer'), expirationDate);
		},

		/**
		* Call user profile services to retrieve the loginToken
		*/
		retrieveLoginToken: function() {
			var options = {
				'url': 'v1/loginToken',
				'dataType': 'json',
				'type': 'POST'
			};

			return this.glassContext.getCoreSvc('.Ajax').ajax(options)
				.then(function(response) {

					const payload = response.data;
					payload.affinityHeader = response.jqXHR.getResponseHeader('x-ca-affinity');
					return Promise.resolve(payload);
				}.bind(this)).catch(this.handleLoginTokenError.bind(this));
		},

		handleLoginTokenError: function(err) {
			this.logger.error(err);
			return Promise.reject(err);
		},

		getServerURL: function() {
			return window.location.origin;
		}
	});

	return QRSlideoutView;
});