/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 1999-2022 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 A service request to let a TrustCenter join an EST-Server
 */

var ServiceRequestModel	= require('pki-as-a-service/service/ServiceRequestModel').ServiceRequestModel;
var SubjectDAO		= require('scsh/pki-db/db/SubjectDAO').SubjectDAO;



/**
 * Data model for joining an EST-Server
 *
 * @constructor
 */
function JoinESTServerServiceRequestModel(service, bo) {
	ServiceRequestModel.call(this, service, bo);
}

JoinESTServerServiceRequestModel.prototype = Object.create(ServiceRequestModel.prototype);
JoinESTServerServiceRequestModel.constructor = JoinESTServerServiceRequestModel;

exports.JoinESTServerServiceRequestModel = JoinESTServerServiceRequestModel;



JoinESTServerServiceRequestModel.prototype.getForm = function(user) {
	if (this.form == undefined) {
		var editable = (user.id == this.getOriginatorId()) &&
			((this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_NEW) ||
			(this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_EDIT) ||
			(this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_SUBMIT));

		var selectionListServer = [];
		if (this.bo.lifecycle <= ServiceRequestModel.LIFECYCLE_SUBMIT) {
			var editableESTServer = true;
			var subjectDAO = this.service.daof.getSubjectDAO();
			var serverList = subjectDAO.listSubjectsByType(SubjectDAO.TYPE_EST_Server);
			for (var i = 0; i < serverList.length; i++) {
				var server = serverList[i];

				if (this.hasJoinedToServer(server)) {
					GPSystem.log(GPSystem.DEBUG, module.id, "Skip already joined server " + server);
					continue;
				}

				if (server.lifecycle == SubjectDAO.LIFECYCLE_PUBLIC ||
					server.getContent().trustCenter == this.getOriginatorId()) {
					selectionListServer.push(
						{ id: server.id, value: server.name, selected: this.model.estServer == server.id }
					);
				}
			}
		} else {
			var editableESTServer = false;
			var estServer = this.getRecipient();
			selectionListServer.push(
				{ id: estServer.getId(), value: estServer.getName(), selected: true }
			);
		}

		// Add the trustcenter's signer certificates
		// to the selection list of trusted certificates
		var selectionListCert = [];
		var trustCenter = this.getOriginator();
		var caList = trustCenter.getCAList();
		for (var i = 0; i < caList.length; i++) {
			var holder = caList[i];
			var e = { id: holder.certId, value: holder.name};
			if (this.model.trustedCA != null && this.model.trustedCA.indexOf(holder.certId) >= 0) {
				e.selected = true;
			}

			selectionListCert.push(e);
		}

		// Add the other trusted certificates to the selection list

		// TODO TrustCenter.trustedCA may change because a certificate can be untrusted
		// An untrusted certificate will stay in content.trustedCA of this sr until the next save operation
		var trustedCerts = trustCenter.bo.getContent().trustedCA;
		if (trustedCerts) {
			var certDAO = this.service.daof.getCertificateDAO();
			var holderDAO = this.service.daof.getHolderDAO();
			var subjectDAO = this.service.daof.getSubjectDAO();
			for (var i = 0; i < trustedCerts.length; i++) {
				var trustedCertId = trustedCerts[i];
				var cert = certDAO.getCertificateById(trustedCertId);
				var holder = holderDAO.getHolderById(cert.holderId);

				var e = { id: trustedCertId, value: holder.name};
				if (this.model.trustedCA != null && this.model.trustedCA.indexOf(trustedCertId) >= 0) {
					e.selected = true;
				}

				selectionListCert.push(e);
			}
		} else {

		}

		var selectionListIssuer = [];
		var caList = trustCenter.getCAList();
		for (var i = 0; i < caList.length; i++) {
			var ca = caList[i];

			var e = { id: ca.id, value: ca.name };
			if (this.model.issuer != null && this.model.issuer.indexOf(ca.id) >= 0) {
				e.selected = true;
			}

			selectionListIssuer.push(e);
		}

		this.form = [{
			id: "estConfiguration",
			legend: "msg.joinest.estConfiguration",
			fields: [
				{ id: "estServer", label: "msg.joinest.estServer", type: "select", multiselect: false, editable: editableESTServer, required: editableESTServer, value: selectionListServer },
				{ id: "trustedCA", label: "msg.joinest.trustedCA", type: "select", multiselect: true, editable: true, required: true, value: selectionListCert },
				{ id: "issuer", label: "msg.joinest.issuer", type: "select", multiselect: true, editable: true, required: true, value: selectionListIssuer },
				{ id: "retryAfter", label: "msg.joinest.retryAfter", type: "number", min: 1, required: true, editable: true, value: (this.model.retryAfter ? this.model.retryAfter : 120) },
				{ id: "autoEnroll", label: "msg.joinest.autoEnroll", type: "checkbox", value: "", checked: this.model.autoEnroll ? this.model.autoEnroll : false, editable: true}
			]},
		];
	}

	return this.form;
}



JoinESTServerServiceRequestModel.prototype.getActionList = function(user) {
	if (this.actionList != undefined) {
		return this.actionList;
	}

	this.actionList = [];

	var trustCenter = this.getOriginator();
	if (trustCenter.isRegistrationOfficer(user)) {
		this.actionList.push("action.save");

		if (this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_EDIT) {
			if (this.model.estServer != null && this.model.estServer > 0 &&
				this.model.trustedCA != null && this.model.trustedCA.length > 0 &&
				this.model.issuer != null && this.model.issuer.length > 0) {
				this.actionList.push("action.submit");
			}
		}

		if (this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_SUBMIT ||
			this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_SUSPENDED) {
			this.actionList.push("action.joinest.reactivate");
		}

		if (this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_INUSE) {
			this.actionList.push("action.joinest.deactivate");
		}
	}

	return this.actionList;
}



JoinESTServerServiceRequestModel.prototype.perform = function(user, action) {
	GPSystem.log(GPSystem.DEBUG, module.id, "perform(" + user.id + "," + action + ")");

	var actionList = this.getActionList(user);

	if (actionList.indexOf(action) == -1) {
		GPSystem.log(GPSystem.DEBUG, module.id, "action list :" + actionList);
		throw new GPError(module.id, GPError.INVALID_DATA, 0, "Action " + action + " unknown");
	}

	var subjectDAO = this.service.daof.getSubjectDAO();

	switch(action) {
		case "action.save":
			if (this.model.estServer) {
				var estServer = subjectDAO.getSubject(this.model.estServer);
				this.updateDetails(estServer.name);
			}

			if (this.bo.lifecycle == ServiceRequestModel.LIFECYCLE_NEW) {
				this.setLifeCycle(ServiceRequestModel.LIFECYCLE_EDIT);
			}
			this.setStatusInfo("Saved");
			break;
		case "action.submit":
			var estServer = subjectDAO.getSubject(this.model.estServer);
			var srDAO = this.service.daof.getServiceRequestDAO();
			srDAO.updateRecipientId(this.bo, estServer);

			this.setLifeCycle(ServiceRequestModel.LIFECYCLE_INUSE);
			this.setStatusInfo("Joined EST-Server");
			break;
		case "action.joinest.deactivate":
			this.setLifeCycle(ServiceRequestModel.LIFECYCLE_SUSPENDED);
			this.setStatusInfo("Deactivate Association");
			break;
		case "action.joinest.reactivate":
			this.setLifeCycle(ServiceRequestModel.LIFECYCLE_INUSE);
			this.setStatusInfo("Reactivate Association");
			break;
	}

	this.commit(user.id);
	return true;
}



JoinESTServerServiceRequestModel.prototype.hasJoinedToServer = function(server) {
	var filter = {
		originatorId: this.getOriginatorId(),
		recipientId: server.id,
		process: "JoinESTServerServiceRequest"
	};

	var srDAO = this.service.daof.getServiceRequestDAO();
	var result = srDAO.listServiceRequestsByFilter(filter);

	return result.length > 0;
}
