/*
 * Copyright (c) 2015 Fraunhofer FOKUS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.openbaton.nfvo.vnfm_reg.tasks;

import org.openbaton.catalogue.mano.common.Event;
import org.openbaton.catalogue.mano.common.LifecycleEvent;
import org.openbaton.catalogue.mano.descriptor.VirtualDeploymentUnit;
import org.openbaton.catalogue.mano.record.Status;
import org.openbaton.catalogue.nfvo.VimInstance;
import org.openbaton.catalogue.nfvo.messages.Interfaces.NFVMessage;
import org.openbaton.catalogue.nfvo.messages.OrVnfmErrorMessage;
import org.openbaton.catalogue.nfvo.messages.OrVnfmGrantLifecycleOperationMessage;
import org.openbaton.nfvo.core.interfaces.VNFLifecycleOperationGranting;
import org.openbaton.nfvo.core.interfaces.VnfPlacementManagement;
import org.openbaton.nfvo.vnfm_reg.tasks.abstracts.AbstractTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * Created by lto on 06/08/15.
 */
@Service
@Scope("prototype")
@ConfigurationProperties
public class GrantoperationTask extends AbstractTask {

    @Autowired
    private VnfPlacementManagement vnfPlacementManagement;

    public boolean isCheckQuota() {
        return checkQuota;
    }

    public void setCheckQuota(boolean checkQuota) {
        this.checkQuota = checkQuota;
    }

    @Value("${nfvo.quota.check:true}")
    private boolean checkQuota;

    @Autowired
    private VNFLifecycleOperationGranting lifecycleOperationGranting;

    @Override
    protected NFVMessage doWork() throws Exception {
        log.info("Executing task: GrantOperation on VNFR: " + virtualNetworkFunctionRecord.getName());

        if (!checkQuota) {
            log.warn("Checking quota is disabled, please consider to enable it");
            LifecycleEvent lifecycleEvent = new LifecycleEvent();
            lifecycleEvent.setEvent(Event.GRANTED);
            lifecycleEvent.setLifecycle_events(new ArrayList<String>());
            if (virtualNetworkFunctionRecord.getLifecycle_event_history() == null)
                virtualNetworkFunctionRecord.setLifecycle_event_history(new HashSet<LifecycleEvent>());
            virtualNetworkFunctionRecord.getLifecycle_event_history().add(lifecycleEvent);
            saveVirtualNetworkFunctionRecord();
            log.debug("Hibernate version is: " + virtualNetworkFunctionRecord.getHb_version());
            OrVnfmGrantLifecycleOperationMessage nfvMessage = new OrVnfmGrantLifecycleOperationMessage();
            nfvMessage.setGrantAllowed(true);
            nfvMessage.setVduVim(new HashMap<String, VimInstance>());
            for (VirtualDeploymentUnit virtualDeploymentUnit : virtualNetworkFunctionRecord.getVdu())
                nfvMessage.getVduVim().put(virtualDeploymentUnit.getId(), vnfPlacementManagement.choseRandom(virtualDeploymentUnit.getVimInstanceName()));
            nfvMessage.setVirtualNetworkFunctionRecord(virtualNetworkFunctionRecord);
//                OrVnfmGenericMessage nfvMessage = new OrVnfmGenericMessage(virtualNetworkFunctionRecord, Action.GRANT_OPERATION);
            return nfvMessage;
        }
        else{
            Map<String, VimInstance> vimInstancesChosen = lifecycleOperationGranting.grantLifecycleOperation(virtualNetworkFunctionRecord);
            log.debug("VimInstances chosen are: " + vimInstancesChosen);
            if (vimInstancesChosen.size() == virtualNetworkFunctionRecord.getVdu().size()) {
                log.info("Finished task: GrantOperation on VNFR: " + virtualNetworkFunctionRecord.getName());
                LifecycleEvent lifecycleEvent = new LifecycleEvent();
                lifecycleEvent.setEvent(Event.GRANTED);
                lifecycleEvent.setLifecycle_events(new ArrayList<String>());
                if (virtualNetworkFunctionRecord.getLifecycle_event_history() == null)
                    virtualNetworkFunctionRecord.setLifecycle_event_history(new HashSet<LifecycleEvent>());
                virtualNetworkFunctionRecord.getLifecycle_event_history().add(lifecycleEvent);
                saveVirtualNetworkFunctionRecord();
                log.debug("Hibernate version is: " + virtualNetworkFunctionRecord.getHb_version());
                OrVnfmGrantLifecycleOperationMessage nfvMessage = new OrVnfmGrantLifecycleOperationMessage();
                nfvMessage.setGrantAllowed(true);
                nfvMessage.setVduVim(vimInstancesChosen);
                nfvMessage.setVirtualNetworkFunctionRecord(virtualNetworkFunctionRecord);
//                OrVnfmGenericMessage nfvMessage = new OrVnfmGenericMessage(virtualNetworkFunctionRecord, Action.GRANT_OPERATION);
                return nfvMessage;
            } else {
                // there are not enough resources for deploying VNFR
                log.error("Not enough resources for deploying VirtualNetworkFunctionRecord " + virtualNetworkFunctionRecord.getName());
                virtualNetworkFunctionRecord.setStatus(Status.ERROR);
                saveVirtualNetworkFunctionRecord();
                vnfmManager.findAndSetNSRStatus(virtualNetworkFunctionRecord);
                OrVnfmErrorMessage nfvMessage = new OrVnfmErrorMessage(virtualNetworkFunctionRecord, "Not enough resources for deploying VirtualNetworkFunctionRecord " + virtualNetworkFunctionRecord.getName());
                return nfvMessage;
            }
        }
    }

    @Override
    public boolean isAsync() {
        return true;
    }
}

@@ -3937,16 +3937,155 @@
   else%7B%0A
+            //Save the vnfr since in the grantLifecycleOperation method we use vdu.getId()%0A            saveVirtualNetworkFunctionRecord();%0A
         
@@ -6059,39 +6059,14 @@
     
-OrVnfmErrorMessage nfvMessage =
+return
  new
@@ -6229,43 +6229,8 @@
 ));%0A
-                return nfvMessage;%0A
     

Save vnfr before operation grantLifecycleOperation since in such method we use vdu.getId() which won't exists otherwise