/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 1999-2010 CardContact Software & System Consulting
 * |'##> <##'|  Andreas Schwier, 32429 Minden, Germany (www.cardcontact.de)
 *  ---------
 *
 *  This file is part of OpenSCDP.
 *
 *  OpenSCDP is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  OpenSCDP is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with OpenSCDP; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * @fileoverview Base class for all remote card related mechanisms
 */



var CommonUI			= require('scsh/srv-cc1/CommonUI').CommonUI;
var CardAction			= require('scsh/srv-cc1/CardAction').CardAction;
var RegisterMyTokenRequestModel	= require('pki-as-a-service/processes/RegisterMyTokenRequestModel').RegisterMyTokenRequestModel;
var ServiceRequestModel		= require('pki-as-a-service/service/ServiceRequestModel').ServiceRequestModel;


function RegistrationWizard(ui, sr) {
	CardAction.call(this, ui);
	this.sr = sr;
}


RegistrationWizard.prototype = Object.create(CardAction.prototype);
RegistrationWizard.constructor = RegistrationWizard;

exports.RegistrationWizard = RegistrationWizard;



RegistrationWizard.prototype.getPage = function(req, res, url) {
	GPSystem.log(GPSystem.DEBUG, module.id, "sr id : " + this.sr.bo.id + ", sr lifecycle : " + this.sr.getLifeCycle() + ", sr state : " + this.sr.bo.state);

	this.ui.clearResultMessage();
	switch (this.sr.getLifeCycle()) {
		case ServiceRequestModel.LIFECYCLE_NEW:
			if (req.method == "POST" && req.parameters.email) { // e-mail address received
				GPSystem.log(GPSystem.DEBUG, module.id, "Process e-mail " + req.parameters.email);
				this.sr.setEmail(req.parameters.email);
			} else {
				if (this.sr.model.email) {
					this.ui.setErrorMessage("Invalid e-mail address", "'" + this.sr.model.email + "' is not a valid e-mail address");
				}
				// enter e-mail
				var page = this.getEmailPage(req, res, url);
			}
			break;
		case ServiceRequestModel.LIFECYCLE_VALIDATE:
			if (this.sr.getActivationTries() < RegisterMyTokenRequestModel.INITIAL_ACTIVATION_TRIES) {
				this.ui.setErrorMessage(RegisterMyTokenRequestModel.STATE_WRONG_ACTIVATION_CODE);
			}
			if (req.method == "POST" && req.parameters.activationCode) {
				GPSystem.log(GPSystem.DEBUG, module.id, "Process activation code " + req.parameters.activationCode);
				this.sr.verifyActivationCode(req.parameters.activationCode);
			} else if (req.method == "POST" && req.parameters.cancel) {
				this.sr.cancelServiceRequest();
			} else if (req.method == "POST" && req.parameters.email) {
				GPSystem.log(GPSystem.DEBUG, module.id, "Send new activation code to " + req.parameters.email);
				this.sr.setEmail(req.parameters.email);
			} else {
				if (req.queryString == "settings")  {
					var page = this.getActivationRequestPage(req, res, url);
				} else {
					var page = this.getVerificationPage(req, res, url);
				}
			}
			break;
		case ServiceRequestModel.LIFECYCLE_RETURNED:
			var page = this.getCanceledEnrollmentPage(req, res);
			break;
		case ServiceRequestModel.LIFECYCLE_APPROVE:
			var page = this.getApprovalPage(req, res);
			break;
		case ServiceRequestModel.LIFECYCLE_ERROR:
			if (this.sr.model.activationTries <= 0) {
				var page = this.getBlockedActivationCodePage(req, res);
			} else if (this.sr.model.activationRequests <= 0) {
				var page = this.getBlockedActivationRequestPage(req, res);
			} else {
				var page = this.getErrorPage(req, res);
			}
			break;
		case ServiceRequestModel.LIFECYCLE_TERMINATED:
		case ServiceRequestModel.LIFECYCLE_REJECTED:
			var page = this.getClosedRegistrationPage(req, res);
			break;
		case ServiceRequestModel.LIFECYCLE_COMPLETE:
			this.state = RegisterMyTokenRequestModel.STATE_COMPLETED;
			this.ui.authorizationState = "AUTHORIZED";

			// Update session user object to reflect
			this.ui.session.user = this.ui.service.authorizationManager.getUser(this.sr.model.tokenId);

			var page = null;
			var subject = this.sr.getOriginator();
			if (!(subject.isSRNotificationAllowed() && subject.isUPDNotificationAllowed())) {
				if (req.method == "POST") {
					if (req.parameters.allowSRNotification || req.parameters.allowUPDNotification) {
						GPSystem.log(GPSystem.DEBUG, module.id, "Set allowSRNotification to " + req.parameters.allowSRNotification
						+ " and allowUPDNotification to " + req.parameters.allowUPDNotification);
						this.sr.setNotificationSettings(req.parameters.allowSRNotification == "on",
										req.parameters.allowUPDNotification == "on");
						this.sr.commit(this.ui.session.user.id);
					}
					this.notificationSettingsProcessed = true;
				} else if (!this.notificationSettingsProcessed) {
					var page = this.getNotificationSettingsPage(res, res, subject);
				}
			}
			break;
		default:
			var page = this.getErrorPage(req, res);
			break;
	}
	return page;
}



/**
 * Generate a HTML template
 *
 * @param {String[]} url the array of URL elements
 * @returns the HTML page template
 * @type XML
 */
RegistrationWizard.prototype.generateTemplate = function(url) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var prefix = "";
	for (var i = 1; i < url.length; i++) {
		prefix += "../";
	}

	var pagetemplate =
		<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" >
			<head>
				<title>PKI-as-a-Service Registration</title>
				<link rel="stylesheet" type="text/css" href={prefix + "../css/style.css"}/>
			</head>
			<body>
				<div align="left">
					<a href="http://www.cardcontact.de"><img src={prefix + "../images/banner.jpg"} width="750" height="80" border="0"/></a>
				</div>

				<div id="main">
					<div id="user" align="right">
						<p>{this.sr.getEmail() ? this.sr.getEmail() : ""} <a href={prefix + url[0] + "/logout"}>Logout Token</a></p>
					</div>
					<div id="error"/>
					<div id="content"/>
					<p class="copyright">(c) Copyright 2003 - 2017<a href="http://www.cardcontact.de">CardContact</a> Systems GmbH, Minden, Germany</p>
				</div>
			</body>
		</html>


	if (this.ui.resultCode != null) {
		var page =
			<div>
				<p id="result" class= { this.ui.resultClass }>{ this.ui.resultMessage } (<b id="resultCode">{ this.ui.resultCode }</b>)</p>
			</div>

		var div = pagetemplate.body..div.(@id == "error");
		div.appendChild(page);
	}

	return pagetemplate;
}



/**
 * Send page after embedding in the HTML template
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 * @param {XML} page the page contents
 */
RegistrationWizard.prototype.sendPage = function(req, res, url, page) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	if (this.sr.getStatusInfo() != RegisterMyTokenRequestModel.STATE_COMPLETED) {
		var template = this.generateTemplate(url);
	} else {
		var template = this.ui.generateTemplate(url);
	}
	var c = template..div.(@id == "content");
	c.div = page;

	res.setContentType("application/xhtml+xml");
	res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
	res.addHeader("Pragma", "no-cache");
	res.print('<?xml version="1.0" encoding="UTF-8" standalone="no"?>');
	res.print('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n');
	res.print(template.toXMLString());
}



/**
 * Serve the error page if the service request is in an undefined state
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getErrorPage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Registration Failed</h1>
			<p>An error occured during your registration. The case will be handled by an administrator. You will get an e-mail notification when the registration can be continued.</p>
			<p>{this.sr.getStatusInfo()}</p>
		</div>

	return page;
}



/**
 * Error page if more than three times a new Activation Code
 * was requested.
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getBlockedActivationRequestPage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Too Many Activation Code Requests</h1>
			<p>You requested a lot of activation codes. To secure your account from fraud this registration will be reviewed by the Registration Officer. You will get an e-mail notification when the registration can be continued.</p>
		</div>

	return page;
}



/**
 * Error page if the Activation Code is blocked
 * because a wrong code was entered three times.
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getBlockedActivationCodePage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Blocked Activation Code</h1>
			<p>You entered a wrong Activation Code three times. To secure your account from fraud this registration will be reviewed by the Registration Officer. You will get an e-mail notification when the registration can be continued.</p>
		</div>

	return page;
}



/**
 * Notifiaction page in lifecycle Returned
 * if the user canceled an enrollement.
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getCanceledEnrollmentPage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Canceled Registration</h1>
			<p>The enrollment was canceled by the user. The corresponding Registration Officer will handle this process.</p>
		</div>

	return page;
}



/**
 * Notification if approval is needed.
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getApprovalPage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Registration Request forwarded for Approval</h1>
			<p>Your registration request will be reviewed by the Registration Officer. You will get an e-mail notification when the registration can be continued.</p>
		</div>

	return page;
}



RegistrationWizard.prototype.getEmailPage = function(req, res, url) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Register Token</h1>

			<form class="pure-form" action="" method="post" enctype="multipart/form-data">
				<p>This token is not registered yet.</p>

				<p>If you like to register for the PKI-as-a-Service
				platform, then please enter a valid e-mail address to which the token will be assigned.
				An activation code will be send to the e-mail address for confirmation.</p>

				<p>By registering your token you consent to the
				<a href="https://www.cardcontact.de/products/pki-as-a-service-terms.html" target="_blank">terms and conditions</a> for using the
				PKI-as-a-Service portal.</p>
				<label>e-mail</label>
				<input name="email" type="email" required="true" value=""/>
				<button class="pure-button" type="submit">Send</button>
			</form>


		</div>

	return page;
}



RegistrationWizard.prototype.getVerificationPage = function(req, res, url) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Register Token</h1>

			<p>To complete the registration you must enter the activation code we send to <b>{this.sr.getEmail()}</b> to verify your account.</p>
			<p>By entering the activation code you consent to the
			<a href="https://www.cardcontact.de/products/pki-as-a-service-terms.html" target="_blank">terms and conditions</a>
			for using the PKI-as-a-Service portal.</p>

			<form class="pure-form" action="" method="post" enctype="multipart/form-data">
				<label>Activation Code</label>
				<input name="activationCode" type="text" value="" required = "true"/>
				<button class="pure-button" type="submit">Send</button>
			</form>
		</div>

	if (this.sr.model.activationRequests > 0) {
		page.appendChild(<p><a href={this.ui.homeURL(url) + "?settings"}>Didn't get an activation code?</a></p>);
	}
	return page;
}



RegistrationWizard.prototype.getActivationRequestPage = function(req, res, url) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<p><a href="paas">{String.fromCharCode(0xAB) + "Back"}</a></p>

			<h1>Register Token</h1>
		</div>

	if (this.sr.model.raRoleID) {
		var form =
			<form class="pure-form" action="" method="post" enctype="multipart/form-data">
				<p>You didn't get your activation code or lost it? Request a new one:</p>
				<label>e-mail</label>
				<input name="email" type="email" required="true" readonly="readonly" value={this.sr.getEmail()}/>
				<button class="pure-button" type="submit">Request New Activation Code</button>
			</form>;
		page.appendChild(form);

		var form =
			<form class="pure-form pure-form-aligned" action="" method="post" enctype="multipart/form-data">
				<fieldset>
					<p>If the e-mail address doesn't belong to you then please cancel the registration.</p>
					<div class="pure-control-group">
						<input name="cancel" type="hidden" value="true"/>
						<p><button class="pure-button" type="submit">Cancel Registration</button></p>
					</div>
				</fieldset>
			</form>;
		page.appendChild(form);
	} else {
		var form =
			<form class="pure-form" action="" method="post" enctype="multipart/form-data">
				<p>You didn't get your activation code or lost it ? Request a new one:</p>
				<label>e-mail</label>
				<input name="email" type="email" required="true" value={this.sr.getEmail()}/>
				<button class="pure-button" type="submit">Request New Activation Code</button>
			</form>;
		page.appendChild(form);
	}

	return page;
}



/**
 * Notifiaction page if the registration
 * was closed (rejected) by
 * the Registration Officer.
 *
 * @param {HttpRequest} req the request object
 * @param {HttpResponse} req the response object
 */
RegistrationWizard.prototype.getClosedRegistrationPage = function(req, res) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var page =
		<div>
			<h1>Closed Registration</h1>
			<p>This registration was closed by the corresponding Registration Officer.</p>
		</div>

	return page;
}



RegistrationWizard.prototype.getNotificationSettingsPage = function(req, res, subject) {
	default xml namespace = "http://www.w3.org/1999/xhtml";

	var srInput = <input type="checkbox" id="allowSRNotification" name="allowSRNotification" style="accent-color: #ffcc66;" />
	if (subject.isSRNotificationAllowed()) {
		srInput.@checked = "checked";
	}

	var updInput = <input type="checkbox" id="allowUPDNotification" name="allowUPDNotification" style="accent-color: #ffcc66;" />
	if (subject.isUPDNotificationAllowed()) {
		updInput.@checked = "checked";
	}

	var page =
		<div>
			<h1>Notification Settings</h1>

			<p>Please choose whether you like to receive e-mail notifications. You can update the notification settings in any of your Register Token Service Requests.</p>

			<form class="pure-form pure-form-stacked" action="" method="post" enctype="multipart/form-data">
				<label for="allowSRNotification">
					{ srInput }
					use this e-mail address to notify about life-cycle changes in service requests that I started or that I'm involved in
				</label>

				<label for="allowUPDNotification">
					{ updInput }
					use this e-mail address to inform about software updates for the SmartCard-HSM or the PKI-as-a-Service portal
				</label>
				<br/>
				<button class="pure-button" type="submit">Submit</button>
			</form>
		</div>

	return page;
}
