/*******************************************************************************
 * Copyright (c) 2013-2020 LAAS-CNRS (www.laas.fr)
 * 7 Colonel Roche 31077 Toulouse - France
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * Initial Contributors:
 *     Thierry Monteil : Project manager, technical co-manager
 *     Mahdi Ben Alaya : Technical co-manager
 *     Samir Medjiah : Technical co-manager
 *     Khalil Drira : Strategy expert
 *     Guillaume Garzone : Developer
 *     François Aïssaoui : Developer
 *
 * New contributors :
 *******************************************************************************/
package org.eclipse.om2m.core.controller;

import java.util.List;

import org.eclipse.om2m.commons.constants.Constants;
import org.eclipse.om2m.commons.constants.MimeMediaType;
import org.eclipse.om2m.commons.constants.Operation;
import org.eclipse.om2m.commons.constants.ResourceStatus;
import org.eclipse.om2m.commons.constants.ResourceType;
import org.eclipse.om2m.commons.constants.ResponseStatusCode;
import org.eclipse.om2m.commons.constants.ShortName;
import org.eclipse.om2m.commons.entities.AccessControlOriginatorEntity;
import org.eclipse.om2m.commons.entities.AccessControlPolicyEntity;
import org.eclipse.om2m.commons.entities.AccessControlRuleEntity;
import org.eclipse.om2m.commons.entities.CSEBaseEntity;
import org.eclipse.om2m.commons.entities.DynamicAuthorizationConsultationEntity;
import org.eclipse.om2m.commons.entities.RemoteCSEEntity;
import org.eclipse.om2m.commons.entities.ResourceEntity;
import org.eclipse.om2m.commons.entities.SubscriptionEntity;
import org.eclipse.om2m.commons.exceptions.AccessDeniedException;
import org.eclipse.om2m.commons.exceptions.BadRequestException;
import org.eclipse.om2m.commons.exceptions.ConflictException;
import org.eclipse.om2m.commons.exceptions.NotPermittedAttrException;
import org.eclipse.om2m.commons.exceptions.ResourceNotFoundException;
import org.eclipse.om2m.commons.resource.RemoteCSE;
import org.eclipse.om2m.commons.resource.RequestPrimitive;
import org.eclipse.om2m.commons.resource.ResponsePrimitive;
import org.eclipse.om2m.commons.utils.Util.DateUtil;
import org.eclipse.om2m.core.datamapper.DataMapperSelector;
import org.eclipse.om2m.core.entitymapper.EntityMapperFactory;
import org.eclipse.om2m.core.notifier.Notifier;
import org.eclipse.om2m.core.remotecse.RemoteCseService;
import org.eclipse.om2m.core.router.Patterns;
import org.eclipse.om2m.core.urimapper.UriMapper;
import org.eclipse.om2m.core.util.ControllerUtil;
import org.eclipse.om2m.core.util.ControllerUtil.UpdateUtil;
import org.eclipse.om2m.persistence.service.DAO;

/**
 * Controller for remote CSE
 *
 */
public class RemoteCSEController extends Controller {

	/**
	 * Create the resource in the system according to the representation
	 * @param request
	 * @return response
	 */
	@Override
	public ResponsePrimitive doCreate(RequestPrimitive request) {
		/*
		 * remoteCSE creation procedure
		 * 
		 * @resourceName			NP
		 * resourceType				NP
		 * resourceID				NP
		 * parentID					NP
		 * accessControlPolicyIDs	O
		 * creationTime				NP
		 * expirationTime			O
		 * lastModifiedTime			NP
		 * labels					O
		 * announceTo				O
		 * announcedAttribute		O
		 * 
		 * cseType					O
		 * poa						O
		 * CseBase					M
		 * CSE-ID					M
		 * M2M-EXT-ID				O
		 * Trigger-Recipient-ID		O
		 * requestReachability		M
		 * nodeLink					NP
		 * 
		 */

		ResponsePrimitive response = new ResponsePrimitive(request);
		Patterns patterns = new Patterns();

		// get the dao of the parent
		DAO<ResourceEntity> dao = (DAO<ResourceEntity>) patterns.getDAO(request.getTo(), dbs);
		if (dao == null){
			throw new ResourceNotFoundException("Cannot find parent resource");
		}
		// get the parent entity
		ResourceEntity parentEntity = (ResourceEntity)dao.find(transaction, request.getTo());
		// check the parent existence
		if (parentEntity == null) {
			throw new ResourceNotFoundException("Cannot find the parent resource");
		}
		
		// lock parent
		transaction.lock(parentEntity);

		// get lists to change in the method corresponding to specific object
		List<AccessControlPolicyEntity> acpsToCheck = null;
		List<RemoteCSEEntity> remoteCSEs = null;
		List<SubscriptionEntity> subscriptions = null;

		// different cases
		// case parent is CSEBase
		if (parentEntity.getResourceType().intValue() == (ResourceType.CSE_BASE)) {
			CSEBaseEntity cseB = (CSEBaseEntity) parentEntity;
			acpsToCheck = cseB.getAccessControlPolicies();
			remoteCSEs = cseB.getRemoteCses();
			subscriptions = cseB.getSubscriptions();
		}

		// check if originator is provided
		if (request.getFrom() == null){
			throw new AccessDeniedException("No originator provided");
		}
		boolean newOriginator = false;
		if (originatorExists(request.getFrom())) {
			// check access control policy of the originator
			checkACP(acpsToCheck, request.getFrom(), Operation.CREATE);
		} else {
			newOriginator = true;
		}
		
		// check if content is present
		if (request.getContent() == null){
			throw new BadRequestException("A content is requiered for RemoteCSE creation");
		}
		// get the object from the representation
		RemoteCSE remoteCse = null;
		try{
			if(request.getRequestContentType().equals(MimeMediaType.OBJ)){
				remoteCse = (RemoteCSE) request.getContent();
			} else {
				remoteCse = (RemoteCSE)DataMapperSelector.getDataMapperList()
						.get(request.getRequestContentType()).stringToObj((String)request.getContent());				
			}

		} catch (ClassCastException e){
			throw new BadRequestException("Incorrect resource representation in content");
		}
		if (remoteCse == null){
			throw new BadRequestException("Error in provided content");
		}

		RemoteCSEEntity remoteCseEntity = new RemoteCSEEntity();
		// check attributes
		// @resourceName 		NP 
		// Resource Type 		NP
		// resourceID 			NP
		// parentID 			NP
		// lastModifiedTime 	NP
		// creationTime 		NP
		// labels				O
		ControllerUtil.CreateUtil.fillEntityFromGenericResource(remoteCse, remoteCseEntity);
		
		// nodelink				NP
		if (remoteCse.getNodeLink() != null){
			throw new NotPermittedAttrException("NodeLink is Not Permitted");
		}

		// CseBase					M
		if (remoteCse.getCSEBase() == null) {
			throw new BadRequestException("CseBase is Mandatory");
		} else {
			remoteCseEntity.setRemoteCseUri(remoteCse.getCSEBase());
		}
		// CSE-ID					M
		if (remoteCse.getCSEID() == null) {
			throw new BadRequestException("CSE-ID is mandatory");
		} else {
			remoteCseEntity.setRemoteCseId(remoteCse.getCSEID());
		}
		// requestReachability		M
		if (remoteCse.isRequestReachability() == null){
			throw new BadRequestException("Request Reachability is mandatory");
		} else {
			remoteCseEntity.setRequestReachability(remoteCse.isRequestReachability());
		}
		// accessControlPolicyIDs	O
		if (!remoteCse.getAccessControlPolicyIDs().isEmpty()){		
			remoteCseEntity.setAccessControlPolicies(
					ControllerUtil.buildAcpEntityList(remoteCse.getAccessControlPolicyIDs(), transaction));
		} else {
			remoteCseEntity.getAccessControlPolicies().addAll(acpsToCheck);
		}
		// dynamicAuthorizationConsultationIDs O
		if (!remoteCse.getDynamicAuthorizationConsultationIDs().isEmpty()) {
			remoteCseEntity.setDynamicAuthorizationConsultations(
					ControllerUtil.buildDacEntityList(remoteCse.getDynamicAuthorizationConsultationIDs(), transaction));
		}
		// expiration time 			O
		if (remoteCse.getExpirationTime() != null){
			remoteCseEntity.setExpirationTime(remoteCse.getExpirationTime());
		}
		// labels					O
		if (!remoteCse.getLabels().isEmpty()){
			remoteCseEntity.setLabelsEntitiesFromSring(remoteCse.getLabels());
		}
		// announceTo				O
		if (!remoteCse.getAnnounceTo().isEmpty()){
			remoteCseEntity.getAnnounceTo().addAll(remoteCse.getAnnounceTo());
		}
		// announcedAttribute		O
		if (!remoteCse.getAnnouncedAttribute().isEmpty()){
			remoteCseEntity.getAnnouncedAttribute().addAll(remoteCse.getAnnouncedAttribute());
		}
		// cseType					O
		if (remoteCse.getCseType() != null) {
			remoteCseEntity.setCseType(remoteCse.getCseType());
		}
		// poa						O
		if (!remoteCse.getPointOfAccess().isEmpty()){
			remoteCseEntity.getPointOfAccess().addAll(remoteCse.getPointOfAccess());
		}

		// M2M-EXT-ID				O
		if(remoteCse.getM2MExtID() != null) {
			remoteCseEntity.setM2mExtId(remoteCse.getM2MExtID());
		}
		// Trigger-Recipient-ID		O
		if (remoteCse.getTriggerRecipientID() != null) {
			remoteCseEntity.setTriggerRecipientID(remoteCse.getTriggerRecipientID());
		}

		// creating the corresponding entity
		String generatedId = generateId("", "");
		remoteCseEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.REMOTE_CSE + Constants.PREFIX_SEPERATOR + generatedId);
		// set name if present and without any conflict
		if (remoteCse.getName() != null){
			if (!patterns.checkResourceName(remoteCse.getName())){
				throw new BadRequestException("Name provided is incorrect. Must be:" + patterns.ID_STRING);
			}
			remoteCseEntity.setName(remoteCse.getName());
		} else {
			remoteCseEntity.setName(ShortName.REMOTE_CSE + "_" + generatedId);
		}
		remoteCseEntity.setHierarchicalURI(parentEntity.getHierarchicalURI() + "/" + remoteCseEntity.getName());
		if (!UriMapper.addNewUri(remoteCseEntity.getHierarchicalURI(), remoteCseEntity.getResourceID(), ResourceType.REMOTE_CSE)){
			throw new ConflictException("Name already present in the parent collection.");
		}
		remoteCseEntity.setCreationTime(DateUtil.now());
		remoteCseEntity.setLastModifiedTime(DateUtil.now());
		remoteCseEntity.setParentID(parentEntity.getResourceID());
		remoteCseEntity.setParentCseBase((CSEBaseEntity) parentEntity);
		remoteCseEntity.setResourceType(ResourceType.REMOTE_CSE);

		if(newOriginator){
			AccessControlPolicyEntity acpEntity = new AccessControlPolicyEntity();
			acpEntity.setCreationTime(DateUtil.now());
			acpEntity.setLastModifiedTime(DateUtil.now());
			acpEntity.setParentID("/" + Constants.CSE_ID);
			acpEntity.setResourceID("/" + Constants.CSE_ID + "/" + ShortName.ACP + Constants.PREFIX_SEPERATOR + generateId());
			acpEntity.setName(ShortName.ACP + ShortName.REMOTE_CSE + Constants.PREFIX_SEPERATOR + generatedId);
			acpEntity.setResourceType(ResourceType.ACCESS_CONTROL_POLICY);
			AccessControlRuleEntity ruleEntity = new AccessControlRuleEntity();
			AccessControlOriginatorEntity originatorEntity = new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY);
			ruleEntity.getAccessControlOriginators().add(originatorEntity);
			ruleEntity.setCreate(true);
			ruleEntity.setRetrieve(true);
			ruleEntity.setUpdate(true);
			ruleEntity.setDelete(true);
			ruleEntity.setNotify(true);
			ruleEntity.setDiscovery(true);
			acpEntity.getSelfPrivileges().add(ruleEntity);
			// Privileges
			ruleEntity = new AccessControlRuleEntity();
			ruleEntity.setCreate(true);
			ruleEntity.setRetrieve(true);
			ruleEntity.setUpdate(true);
			ruleEntity.setDelete(true);
			ruleEntity.setNotify(true);
			ruleEntity.setDiscovery(true);
			ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(request.getFrom()));
			ruleEntity.getAccessControlOriginators().add(new AccessControlOriginatorEntity(Constants.ADMIN_REQUESTING_ENTITY));
			acpEntity.getPrivileges().add(ruleEntity);
			acpEntity.setHierarchicalURI("/" + Constants.CSE_ID + "/" + acpEntity.getName());
			UriMapper.addNewUri(acpEntity.getHierarchicalURI(), acpEntity.getResourceID(), ResourceType.ACCESS_CONTROL_POLICY);
			dbs.getDAOFactory().getAccessControlPolicyDAO().create(transaction, acpEntity);

			AccessControlPolicyEntity acpDB = dbs.getDAOFactory().getAccessControlPolicyDAO().find(transaction, acpEntity.getResourceID());
			CSEBaseEntity cseBase = dbs.getDAOFactory().getCSEBaseDAO().find(transaction, "/" + Constants.CSE_ID);
			cseBase.getChildAccessControlPolicies().add(acpDB);
			dbs.getDAOFactory().getCSEBaseDAO().update(transaction, cseBase);

			remoteCseEntity.getAccessControlPolicies().add(acpDB);
			remoteCseEntity.setGeneratedAcp(acpDB);
		}

		// Create remoteCSE in database
		dbs.getDAOFactory().getRemoteCSEDAO().create(transaction, remoteCseEntity);

		// Get the managed object from db
		RemoteCSEEntity csrDB = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, remoteCseEntity.getResourceID());

		// Add the remoteCSE to the CSEBase list
		remoteCSEs.add(csrDB);
		dao.update(transaction, parentEntity);
		
		// update link with remoteCseEntity - DacEntity
		for(DynamicAuthorizationConsultationEntity dace : csrDB.getDynamicAuthorizationConsultations()) {
			DynamicAuthorizationConsultationEntity daceFromDB = dbs.getDAOFactory().getDynamicAuthorizationDAO().find(transaction, dace.getResourceID());
			daceFromDB.getLinkedRemoteCSEEntities().add(csrDB);
			dbs.getDAOFactory().getDynamicAuthorizationDAO().update(transaction, daceFromDB);
		}

		// Commit the DB transaction & release lock
		transaction.commit();

		RemoteCseService.getInstance().addRemoteCseAndPublish(csrDB);
		
		Notifier.notify(subscriptions, csrDB, ResourceStatus.CHILD_CREATED);
		// Create the response
		response.setResponseStatusCode(ResponseStatusCode.CREATED);
		// Set the location of the resource
		setLocationAndCreationContent(request, response, csrDB);

		return response;
	}

	@Override
	public ResponsePrimitive doRetrieve(RequestPrimitive request) {
		// Creating the response primitive
		ResponsePrimitive response = new ResponsePrimitive(request);

		// Check existence of the resource
		RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTo());
		if (csrEntity == null) {
			throw new ResourceNotFoundException();
		}
		
		// if resource exists, check authorization
		// retrieve 
		List<AccessControlPolicyEntity> acpList = csrEntity.getAccessControlPolicies();
		checkACP(acpList, request.getFrom(), request.getOperation());
		
		// Mapping the entity with the exchange resource
		RemoteCSE csr = EntityMapperFactory.getRemoteCseMapper().mapEntityToResource(csrEntity, request);
		response.setContent(csr);
		response.setResponseStatusCode(ResponseStatusCode.OK);
		// return the response
		return response;
	}

	/**
	 * Implement the full update method for remoteCSE resource
	 * @param request
	 * @return response
	 */
	@Override
	public ResponsePrimitive doUpdate(RequestPrimitive request) {
		/*
		 * remoteCSE update procedure
		 * 
		 * @resourceName			NP
		 * resourceType				NP
		 * resourceID				NP
		 * parentID					NP
		 * accessControlPolicyIDs	O
		 * creationTime				NP
		 * expirationTime			O
		 * lastModifiedTime			NP
		 * labels					NP
		 * announceTo				O
		 * announcedAttribute		O
		 * 
		 * cseType					NP
		 * poa						O
		 * CseBase					NP
		 * CSE-ID					NP
		 * M2M-EXT-ID				O
		 * Trigger-Recipient-ID		O
		 * requestReachability		O
		 * nodeLink					NP
		 */
		// create the response base
		ResponsePrimitive response = new ResponsePrimitive(request);

		// retrieve the resource from the DB
		RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTo());
		if (csrEntity == null) {
			throw new ResourceNotFoundException();
		}

		// lock entity
		transaction.lock(csrEntity);
		
		// check ACP
		checkACP(csrEntity.getAccessControlPolicies(), request.getFrom(), Operation.UPDATE);
		

		// check if content is present
		if (request.getContent() == null) {
			throw new BadRequestException("A content is requiered for RemoteCSE Update");
		}

		// create the java object from the resource representation
		RemoteCSE csr = null;
		try{
			if (request.getRequestContentType().equals(MimeMediaType.OBJ)){
				csr = (RemoteCSE) request.getContent();
			} else {
				csr = (RemoteCSE)DataMapperSelector.getDataMapperList()
						.get(request.getRequestContentType()).stringToObj((String)request.getContent());				
			}

		} catch (ClassCastException e){
			throw new BadRequestException("Incorrect resource representation in content", e);
		}
		if (csr == null){
			throw new BadRequestException("Error in provided content");
		}

		// check attributes, NP attributes are ignored

		// @resourceName			NP
		// resourceType				NP
		// resourceID				NP
		// parentID					NP
		// creationTime				NP
		// lastModifiedTime			NP
		UpdateUtil.checkNotPermittedParameters(csr);
		// cseType					NP
		if(csr.getCseType() != null){
			throw new BadRequestException("CseType is NP");
		}
		// CseBase					NP
		if(csr.getCSEBase() != null){
			throw new BadRequestException("CseBase is NP");
		}
		// CSE-ID					NP
		if(csr.getCSEID() != null){
			throw new BadRequestException("CseID is NP");
		}
		// nodeLink					NP
		if(csr.getNodeLink() != null){
			throw new BadRequestException("NodeLink is NP");
		}

		RemoteCSE modifiedAttributes = new RemoteCSE();
		// labels					O
		if(!csr.getLabels().isEmpty()){
			csrEntity.setLabelsEntitiesFromSring(csr.getLabels());
			modifiedAttributes.getLabels().addAll(csr.getLabels());
		}
		
		// accessControlPolicyIDs		O
		if (!csr.getAccessControlPolicyIDs().isEmpty()){		
			for(AccessControlPolicyEntity acpe : csrEntity.getAccessControlPolicies()){
				checkSelfACP(acpe, request.getFrom(), Operation.UPDATE);
			}
			csrEntity.setAccessControlPolicies(
					ControllerUtil.buildAcpEntityList(csr.getAccessControlPolicyIDs(), transaction));
			modifiedAttributes.getAccessControlPolicyIDs().addAll(csr.getAccessControlPolicyIDs());
		}
		
		// dynamicAuthorizationConsultationIDs O
		if (!csr.getDynamicAuthorizationConsultationIDs().isEmpty()) {
			csrEntity.setDynamicAuthorizationConsultations(
					ControllerUtil.buildDacEntityList(csr.getDynamicAuthorizationConsultationIDs(), transaction));
			
			// update link with remoteCseEntity - DacEntity
			for(DynamicAuthorizationConsultationEntity dace : csrEntity.getDynamicAuthorizationConsultations()) {
				DynamicAuthorizationConsultationEntity daceFromDB = dbs.getDAOFactory().getDynamicAuthorizationDAO().find(transaction, dace.getResourceID());
				daceFromDB.getLinkedRemoteCSEEntities().add(csrEntity);
				dbs.getDAOFactory().getDynamicAuthorizationDAO().update(transaction, daceFromDB);
			}
		}
		
		// expirationTime			O
		if (csr.getExpirationTime() != null){
			csrEntity.setExpirationTime(csr.getExpirationTime());
			modifiedAttributes.setExpirationTime(csr.getExpirationTime());
		}
		// announceTo				O
		if(!csr.getAnnounceTo().isEmpty()){
			// TODO Announcement in AE update
			csrEntity.getAnnounceTo().clear();
			csrEntity.getAnnounceTo().addAll(csr.getAnnounceTo());
			modifiedAttributes.getAnnounceTo().addAll(csr.getAnnounceTo());
		}
		// announcedAttribute			O
		if(!csr.getAnnouncedAttribute().isEmpty()){
			csrEntity.getAnnouncedAttribute().clear();
			csrEntity.getAnnouncedAttribute().addAll(csr.getAnnouncedAttribute());
			modifiedAttributes.getAnnouncedAttribute().addAll(csr.getAnnouncedAttribute());
		}
		// poa						O
		if (!csr.getPointOfAccess().isEmpty()) {
			csrEntity.getPointOfAccess().clear();
			csrEntity.getPointOfAccess().addAll(csr.getPointOfAccess());
			modifiedAttributes.getPointOfAccess().addAll(csr.getPointOfAccess());
		}
		// M2M-EXT-ID				O
		if (csr.getM2MExtID() != null) {
			csrEntity.setM2mExtId(csr.getM2MExtID());
			modifiedAttributes.setM2MExtID(csr.getM2MExtID());
		}
		// Trigger-Recipient-ID		O
		if (csr.getTriggerRecipientID() != null) {
			csrEntity.setTriggerRecipientID(csr.getTriggerRecipientID());
			modifiedAttributes.setTriggerRecipientID(csr.getTriggerRecipientID());
		}
		// requestReachability		O
		if (csr.isRequestReachability() != null) {
			csrEntity.setRequestReachability(csr.isRequestReachability());
			modifiedAttributes.setRequestReachability(csr.isRequestReachability());
		}

		csrEntity.setLastModifiedTime(DateUtil.now());
		modifiedAttributes.setLastModifiedTime(csrEntity.getLastModifiedTime());
		response.setContent(modifiedAttributes);
		
		// update the resource in the database
		dbs.getDAOFactory().getRemoteCSEDAO().update(transaction, csrEntity);
		
		// commit & release lock
		transaction.commit();
		
		Notifier.notify(csrEntity.getSubscriptions(), csrEntity, ResourceStatus.UPDATED);

		// set response status code
		response.setResponseStatusCode(ResponseStatusCode.UPDATED);
		return response;
	}

	@Override
	/**
	 * Delete the remoteCSE if access control policies are correct
	 */
	public ResponsePrimitive doDelete(RequestPrimitive request) {
		// Generic delete procedure
		ResponsePrimitive response = new ResponsePrimitive(request);

		// retrieve the corresponding resource from database
		RemoteCSEEntity csrEntity = dbs.getDAOFactory().getRemoteCSEDAO().find(transaction, request.getTo());
		if (csrEntity == null) {
			throw new ResourceNotFoundException();
		}
		
		// lock entity
		transaction.lock(csrEntity);

		// check access control policies
		checkACP(csrEntity.getAccessControlPolicies(), request.getFrom(), Operation.DELETE);

		UriMapper.deleteUri(csrEntity.getHierarchicalURI());
		Notifier.notifyDeletion(csrEntity.getSubscriptions(), csrEntity);
		
		// delete the resource in the database
		dbs.getDAOFactory().getRemoteCSEDAO().delete(transaction, csrEntity);
		// commit the transaction & release lock
		transaction.commit();
		
		RemoteCseService.getInstance().removeRemoteCseAndPublish(csrEntity.getName());
		
		// return the response
		response.setResponseStatusCode(ResponseStatusCode.DELETED);
		return response;
	}

}
