/**
 *  ---------
 * |.##> <##.|  Open Smart Card Development Platform (www.openscdp.org)
 * |#       #|
 * |#       #|  Copyright (c) 2016 CardContact Systems GmbH
 * |'##> <##'|  Schuelerweg 38, 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 Core service requests factory
 */


var BaseServiceRequest			= require('scsh/srv-cc1/BaseServiceRequest').BaseServiceRequest;
var ServiceRequestAdapter = require('pki-as-a-service/processes/ServiceRequestAdapter').ServiceRequestAdapter;
var PKIAPIConnector = require('scsh/srv-cc1/PKIAPIConnector').PKIAPIConnector;

var CreateTrustCenterRequestController	= require('pki-as-a-service/processes/CreateTrustCenterRequestController').CreateTrustCenterRequestController;
var CreateTrustCenterRequestModel	= require('pki-as-a-service/processes/CreateTrustCenterRequestModel').CreateTrustCenterRequestModel;

var IssueTokenRequestModel		= require('pki-as-a-service/processes/IssueTokenRequestModel').IssueTokenRequestModel;
var IssueTokenRequestController		= require('pki-as-a-service/processes/IssueTokenRequestController').IssueTokenRequestController;

var ResetRetryCounterServiceRequestModel = require('pki-as-a-service/processes/ResetRetryCounterServiceRequestModel').ResetRetryCounterServiceRequestModel;
var ResetRetryCounterServiceRequestController = require('pki-as-a-service/processes/ResetRetryCounterServiceRequestController').ResetRetryCounterServiceRequestController;

var EnrollServiceRequestModel		= require('pki-as-a-service/processes/EnrollServiceRequestModel').EnrollServiceRequestModel;
var EnrollPersonRequestController	= require('pki-as-a-service/processes/EnrollPersonRequestController').EnrollPersonRequestController;
var EnrollSystemRequestController	= require('pki-as-a-service/processes/EnrollSystemRequestController').EnrollSystemRequestController;
var RegisterMyTokenRequestModel		= require('pki-as-a-service/processes/RegisterMyTokenRequestModel').RegisterMyTokenRequestModel;
var RegisterMyTokenRequestController	= require('pki-as-a-service/processes/RegisterMyTokenRequestController').RegisterMyTokenRequestController;
var ManageRoleServiceRequestModel	= require('pki-as-a-service/processes/ManageRoleServiceRequestModel').ManageRoleServiceRequestModel;
var ManageRoleServiceRequestController	= require('pki-as-a-service/processes/ManageRoleServiceRequestController').ManageRoleServiceRequestController;

var CreateGroupRequestController = require('pki-as-a-service/processes/CreateGroupRequestController').CreateGroupRequestController;
var GroupSignerHolderView = require('pki-as-a-service/holder/GroupSignerHolderView').GroupSignerHolderView;
var GroupMemberHolderView = require('pki-as-a-service/holder/GroupMemberHolderView').GroupMemberHolderView;
var KeyEscrowHolderView = require('pki-as-a-service/holder/KeyEscrowHolderView').KeyEscrowHolderView;
var JoinGroupRequestController = require('pki-as-a-service/processes/JoinGroupRequestController').JoinGroupRequestController;
var IssueKeyDomainMembershipRequestController = require('pki-as-a-service/processes/IssueKeyDomainMembershipRequestController').IssueKeyDomainMembershipRequestController;
var CreateEscrowKeyRequestController = require('pki-as-a-service/processes/CreateEscrowKeyRequestController').CreateEscrowKeyRequestController;
var SendKeyToEscrowRequestController = require('pki-as-a-service/processes/SendKeyToEscrowRequestController').SendKeyToEscrowRequestController;
var ReceiveKeyFromEscrowRequestController = require('pki-as-a-service/processes/ReceiveKeyFromEscrowRequestController').ReceiveKeyFromEscrowRequestController;

var TrustCenter				= require('pki-as-a-service/subjects/TrustCenter').TrustCenter;
var EnrolledSubject			= require('pki-as-a-service/subjects/EnrolledSubject').EnrolledSubject;
var Person					= require('pki-as-a-service/subjects/Person').Person;

var SubjectDAO = require('scsh/pki-db/db/SubjectDAO').SubjectDAO;
var RoleDAO				= require('scsh/pki-db/db/RoleDAO').RoleDAO;



function CoreServiceRequests(service, cfg) {
	this.service = service;
	this.priority = 500;

	this.hasCore = typeof(cfg.core) == "object";
	if (this.hasCore) {
		this.cfg = cfg.core;
		this.service.backendRegistry.addService( {
			id: "core",
			name: "Core Backend Service",
			apiURL: cfg.core.apiURL,
			hasHSMService: true });
	}
}

exports.Plugin = CoreServiceRequests;



CoreServiceRequests.prototype.getAPI = function() {
	return new PKIAPIConnector(this.cfg);
}



CoreServiceRequests.prototype.getFactoryForProcess = function(process) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getFactoryForProcess(" + process + ")");

	switch(process) {
		case "CreateTrustCenterServiceRequest":
		case "IssueTokenServiceRequest":
		case "EnrollPersonServiceRequest":
		case "EnrollSystemServiceRequest":
		case "RegisterMyTokenServiceRequest":
		case "ResetRetryCounterServiceRequest":
		case "ManageRoleServiceRequest":
		case "CreateGroup":
		case "JoinGroup":
		case "IssueKeyDomainMembership":
		case "CreateEscrowKey":
		case "SendKeyToEscrow":
		case "ReceiveKeyFromEscrow":
			return this;
			break;
	}
	return undefined;
}



CoreServiceRequests.prototype.enumerateRunnableProcesses = function(user, processes) {
	GPSystem.log(GPSystem.DEBUG, module.id, "enumerateRunnableProcesses()");

	if (user.roles.indexOf(RoleDAO.ID_Subscriber) >= 0) {
		processes.push( { label: "Create Trust Center", process: "CreateTrustCenterServiceRequest" } );
	}
}



CoreServiceRequests.prototype.enumerateRunnableProcessesForSubject = function(user, subject, processes) {
	GPSystem.log(GPSystem.DEBUG, module.id, "enumerateRunnableProcessesForSubject()");

	var joinGroup = { label: "Join Group", process: "JoinGroup", section: "Key Escrow" };

	if ((subject instanceof EnrolledSubject) && (subject.isManagedBy(user))) {
		processes.push( { label: "Issue Token", process: "IssueTokenServiceRequest" } );
		if (this.hasCore) {
			processes.push(joinGroup);
		}
	}

	// If no role is assigned to the current user
	// then ManageRoleServiceRequest cannot
	// add or remove any role
	if (user.roles && user.roles.length > 0) {
		if ((subject instanceof Person) && (subject.canRead(user))) {
			processes.push( { label: "Manage Role", process: "ManageRoleServiceRequest" } );
		}
	}

	if (subject instanceof TrustCenter) {
		if (subject.isCertificationOfficer(user)) {
			if (this.hasCore) {
				processes.push( { label: "Create Group", process: "CreateGroup", section: "Key Escrow" } );
			}
		}

		if (subject.isRegistrationOfficer(user)) {
			processes.push( { label: "Enroll System", process: "EnrollSystemServiceRequest", section: "X509 RA" } );
			processes.push( { label: "Enroll Person", process: "EnrollPersonServiceRequest", section: "X509 RA" } );

			if (this.hasCore) {
				processes.push(joinGroup);
			}
		}
	}
}



CoreServiceRequests.prototype.enumerateRunnableProcessesForHolderType = function(user, subject, type, processes) {
	GPSystem.log(GPSystem.DEBUG, module.id, "enumerateRunnableProcessesForHolderType()");

	if (this.hasCore && (subject.isManagedBy(user) || (subject.getId() == user.id))) {
		if (subject instanceof TrustCenter) {
			if (type == "GroupMember") {
				processes.push( { label: "Send Key to Escrow", process: "SendKeyToEscrow" } );
				processes.push( { label: "Receive Key from Escrow", process: "ReceiveKeyFromEscrow" } );
				processes.push( { label: "Create Escrow Key", process: "CreateEscrowKey" } );
			}
			if (type == "KeyEscrow") {
				processes.push( { label: "Send Key to Escrow", process: "SendKeyToEscrow" } );
				processes.push( { label: "Receive Key from Escrow", process: "ReceiveKeyFromEscrow" } );
			}
		}
		if (subject instanceof Person) {
			if (type == "GroupMember") {
				processes.push( { label: "Send Key to Escrow", process: "SendKeyToEscrow" } );
				processes.push( { label: "Receive Key from Escrow", process: "ReceiveKeyFromEscrow" } );
			}
		}
	}
}



CoreServiceRequests.prototype.getServiceRequest = function(bo) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getServiceRequest(" + bo + ")");

	switch (bo.process) {
		case "EnrollPersonServiceRequest":
		case "EnrollSystemServiceRequest":
			var sr = new EnrollServiceRequestModel(this.service, bo);
			break;
		case "IssueTokenServiceRequest":
			var sr = new IssueTokenRequestModel(this.service, bo);
			break;
		case "ResetRetryCounterServiceRequest":
			var sr = new ResetRetryCounterServiceRequestModel(this.service, bo);
			break;
		case "RegisterMyTokenServiceRequest":
			var sr = new RegisterMyTokenRequestModel(this.service, bo);
			break;
		case "CreateTrustCenterServiceRequest":
			var sr = new CreateTrustCenterRequestModel(this.service, bo);
			break;
		case "ManageRoleServiceRequest":
			var sr = new ManageRoleServiceRequestModel(this.service, bo);
			break;
		case "CreateGroup":
		case "JoinGroup":
		case "IssueKeyDomainMembership":
		case "CreateEscrowKey":
		case "SendKeyToEscrow":
		case "ReceiveKeyFromEscrow":
			var sr = new ServiceRequestAdapter(this.service, bo, this);
			break;
		default:
			var sr = BaseServiceRequest.deserialize(bo.content);
			break;
	}
	sr.bo = bo;
	sr.id = sr.bo.id;
	sr.service = this.service;
	return sr;
}



CoreServiceRequests.prototype.getControllerForProcess = function(process) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getControllerForProcess(" + process + ")");

	switch(process) {
		case "CreateTrustCenterServiceRequest":
			return new CreateTrustCenterRequestController();
		case "IssueTokenServiceRequest":
			return new IssueTokenRequestController();
		case "ResetRetryCounterServiceRequest":
			return new ResetRetryCounterServiceRequestController();
		case "EnrollPersonServiceRequest":
			return new EnrollPersonRequestController();
		case "EnrollSystemServiceRequest":
			return new EnrollSystemRequestController();
		case "RegisterMyTokenServiceRequest":
			return new RegisterMyTokenRequestController();
		case "ManageRoleServiceRequest":
			return new ManageRoleServiceRequestController();
		case "CreateGroup":
			return new CreateGroupRequestController(this);
		case "JoinGroup":
			return new JoinGroupRequestController(this);
		case "IssueKeyDomainMembership":
			return new IssueKeyDomainMembershipRequestController(this);
		case "CreateEscrowKey":
			return new CreateEscrowKeyRequestController(this);
		case "SendKeyToEscrow":
			return new SendKeyToEscrowRequestController(this);
		case "ReceiveKeyFromEscrow":
			return new ReceiveKeyFromEscrowRequestController(this);
	}
	return undefined;
}



CoreServiceRequests.prototype.getFactoryForHolderType = function(type) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getFactoryForHolderType(" + type + ")");

	switch(type) {
		case "GroupSigner":
		case "GroupMember":
		case "KeyEscrow":
			return this;
			break;
	}
	return undefined;
}



CoreServiceRequests.prototype.getHolderView = function(holder) {
	GPSystem.log(GPSystem.DEBUG, module.id, "getHolderView(" + holder + ")");

	switch (holder.type) {
	case "GroupSigner":
		return new GroupSignerHolderView(this.service, holder);
	case "GroupMember":
		return new GroupMemberHolderView(this.service, holder);
	case "KeyEscrow":
		return new KeyEscrowHolderView(this.service, holder);
	}
}



CoreServiceRequests.prototype.toString = function() {
	return "Core Service Requests";
}
