/**
 *  ---------
 * |.##> <##.|  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 CardAction = require('scsh/srv-cc1/CardAction').CardAction;
var SmartCardHSM = require('scsh/sc-hsm/SmartCardHSM').SmartCardHSM;



function SigningWizard(ui) {
	CardAction.call(this, ui);
	this.operation = [];
}

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

exports.SigningWizard = SigningWizard;


SigningWizard.prototype.getPage = function(req, res, url) {
	GPSystem.log(GPSystem.DEBUG, module.id, "SigningWizard state: " + this.state);
	switch(this.state) {
		case "new":
			var page = this.getSignStartPage(req, res, url);
			this.state = "enumeratekeys";
			break;
		case "enumeratekeys":
			var page = this.getErrorPage(req, res, url);
			this.state = "new";
			break;
		case "enterdata":
			if (req.method == "POST") {
				var page = this.processSignControlForm(req, res, url);
				this.state = "startsign";
			} else {
				var page = this.getSignControlForm(req, res, url);
			}
			break;
		case "startsign":
			var page = this.getSignProgressPage(req, res, url);
			this.state = "sign";
			break;
		case "sign":
			var page = this.getErrorPage(req, res, url);
			this.state = "startsign";
			break;
		case "showresult":
			var page = this.getSignFinishingPage(req, res, url);
			break;
		default:
			var page = CardAction.prototype.getPage.call(this, req, res, url);
	}
	return page;
}



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

	var page =
		<div>
			<h1>Signing Service</h1>
			<p>Enumerate keys... { this.getActivationLink(req, res, -1) }</p>
			<p>Please wait for the green tick to appear. The page will be reloaded automatically if JavaScript is enabled.</p>
			<p>If JavaScript is disabled, then press <a href="">continue</a> after the green tick is shown.</p>
		</div>
	this.signedMessage = "";
	return page;
}



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

	var page =
		<div>
			<h1>Signing Service</h1>
			<p>Error: The SC-HSM has no available signing key.</p>
		</div>
	return page;
}



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

	var page =
		<div>
			<div id="error"/>
			<h1>Signing Service</h1>

			<form action="" method="post" enctype="multipart/form-data">
				<p>Select the signing key:</p>
				<select name="key"/>
				<p>Select the signature algorithm:</p>
				<select name="algorithm">
					<option value="RSA_SHA256">RSA with SHA-256</option>
					<option value="ECDSA_SHA256">ECDSA with SHA-256</option>
					<option value="RSA_SHA1">RSA with SHA-1</option>
					<option value="ECDSA_SHA1">ECDSA with SHA-1</option>
				</select>
				<p>The following data will be signed:</p>
				<input name="data" type="text" value="Hello World"/>
				<button type="submit">Sign</button>
			</form>
		</div>

	this.signedMessage = "";

	var l = page.form.select;
	for each (var alias in this.keys) {
		l[0].appendChild(<option>{alias}</option>);
	}

	return page;
}



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

	this.key = req.parameters.key;
	this.algorithm = req.parameters.algorithm;
	this.data = req.parameters.data;

	return null;
}



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

	var page =
		<div>
			<h1>Signing Service</h1>
			<table class="content">
				<colgroup><col width="120"/><col/></colgroup>
				<tr><td>Message Data</td><td>{this.data}</td></tr>
				<tr><td>Signing Key</td><td>{this.key}</td></tr>
				<tr><td>Signature Algorithm</td><td>{this.algorithm}</td></tr>
			</table>
			<p>Start signing... { this.getActivationLink(req, res, 1) }</p>
			<p>This operation requires PIN verification. Please watch the PIN dialog in the upper right corner
			   of your screen or on your card readers PIN pad.</p>
			<p>Please wait for the green tick to appear. The page will be reloaded automatically if JavaScript is enabled.</p>
			<p>If JavaScript is disabled, then press <a href="">continue</a> after the green tick is shown.</p>
		</div>

	return page;
}



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

	var page =
		<div>
			<h1>Signing Service</h1>
			<h2>Signature computed</h2>
			<table class="content">
				<colgroup><col width="120"/><col/></colgroup>
				<tr><td>Message Data</td><td>{this.data}</td></tr>
				<tr><td>Signing Key</td><td>{this.key}</td></tr>
				<tr><td>Signature Algorithm</td><td>{this.algorithm}</td></tr>
				<tr><td>Signature</td><td>{this.signature}</td></tr>
			</table>
		</div>
	return page;
}



SigningWizard.prototype.handleCardAction = function(card, reqInfo) {
	var sc = new SmartCardHSM(card);

	var devAutCert = sc.readBinary(SmartCardHSM.C_DevAut);
	var crypto = new Crypto();
	var chain = SmartCardHSM.validateCertificateChain(crypto, devAutCert);
	if (chain == null) {
		this.lastMessage = "Could not authenticate SmartCard-HSM";
		return;
	}

	sc.openSecureChannel(crypto, chain.publicKey);

	switch(this.state) {
		case "enumeratekeys":
			this.keys = sc.enumerateKeys();
			if (this.keys.length > 0) {
				this.state = "enterdata";
			} else {
				this.reportError("No keys found on card");
			}
			break;
		case "sign":
			sc.enumerateKeys();
//			print(this.key);
			var signingKey = sc.getKey(this.key);
			var m = new ByteString(this.data, ASCII);

			var alg = Crypto[this.algorithm];

			this.signature = signingKey.sign(alg, m);
			this.state = "showresult";
			break;
		default:
			GPSystem.log(GPSystem.ERROR, module.id, "Unexpected handleCardAction in state " + this.state);
	}
}
