/*
 * (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0 which accompany this distribution.
 *
 * The Apache License is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 */
package io.cloudslang.lang.cli.services;

import org.apache.commons.lang.StringUtils;
import io.cloudslang.score.events.EventConstants;
import io.cloudslang.score.events.ScoreEventListener;
import io.cloudslang.lang.api.Slang;
import io.cloudslang.lang.entities.CompilationArtifact;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static io.cloudslang.lang.entities.ScoreLangConstants.*;

/**
 * @author Bonczidai Levente
 * @since 11/13/2014
 * @version $Id$
 */
@Service
public class ScoreServicesImpl implements ScoreServices{

    @Autowired
    private Slang slang;

    public void subscribe(ScoreEventListener eventHandler, Set<String> eventTypes) {
        slang.subscribeOnEvents(eventHandler, eventTypes);
    }

    /**
     * This method will trigger the flow in an Async matter.
     * @param compilationArtifact the artifact to trigger
     * @param inputs : flow inputs
     * @return executionId
     */
    @Override
	public Long trigger(CompilationArtifact compilationArtifact, Map<String, ? extends Serializable> inputs, Map<String, ? extends Serializable> systemProperties) {
        return slang.run(compilationArtifact, inputs, systemProperties);
    }

    /**
     * This method will trigger the flow in a synchronize matter, meaning only one flow can run at a time.
     * @param compilationArtifact the artifact to trigger
     * @param inputs : flow inputs
     * @return executionId
     */
    @Override
    public Long triggerSync(CompilationArtifact compilationArtifact, Map<String, ? extends Serializable> inputs, Map<String, ? extends Serializable> systemProperties, boolean isQuiet){
        //add start event
        Set<String> handlerTypes = new HashSet<>();
        if(isQuiet){
            handlerTypes.add(EVENT_EXECUTION_FINISHED);
            handlerTypes.add(EVENT_OUTPUT_END);
        }
        else {
            handlerTypes.add(EventConstants.SCORE_FINISHED_EVENT);
            handlerTypes.add(EventConstants.SCORE_ERROR_EVENT);
            handlerTypes.add(EventConstants.SCORE_FAILURE_EVENT);
            handlerTypes.add(SLANG_EXECUTION_EXCEPTION);
            handlerTypes.add(EVENT_EXECUTION_FINISHED);
            handlerTypes.add(EVENT_INPUT_END);
            handlerTypes.add(EVENT_OUTPUT_END);
        }
        
        SyncTriggerEventListener scoreEventListener = new SyncTriggerEventListener();
        slang.subscribeOnEvents(scoreEventListener, handlerTypes);

        Long executionId = trigger(compilationArtifact, inputs, systemProperties);

        while(!scoreEventListener.isFlowFinished()){
            try {
                Thread.sleep(200);
            } catch (InterruptedException ignore) {}
        }
        slang.unSubscribeOnEvents(scoreEventListener);

        String errorMessageFlowExecution = scoreEventListener.getErrorMessage();
        if (StringUtils.isNotEmpty(errorMessageFlowExecution)) {
            if (compilationArtifact.getSystemProperties().size() != 0 && errorMessageFlowExecution.contains("is Required, but value is empty")){
                errorMessageFlowExecution += "\n\nBe sure to include a valid system property file using --spf <path_to_file>";
            }
            // exception occurred during flow execution
            throw new RuntimeException(errorMessageFlowExecution);
        }

        return executionId;
    }
}

@@ -361,16 +361,116 @@
 vices;%0A%0A
+import io.cloudslang.lang.entities.bindings.Input;%0Aimport org.apache.commons.collections4.MapUtils;%0A
 import o
@@ -842,16 +842,45 @@
 izable;%0A
+import java.util.Collection;%0A
 import j
@@ -3509,20 +3509,40 @@
         
-if (
+Collection%3CInput%3E sps = 
 compilat
@@ -3574,16 +3574,38 @@
 erties()
+;%0A%0A            if (sps
 .size() 
@@ -3680,24 +3680,507 @@
 s empty%22))%7B%0A
+                Boolean spMissing = false;%0A                if (systemProperties == null)%7B%0A                    spMissing = true;%0A                %7D%0A%0A                else %7B%0A                    for (Input sp : sps) %7B%0A                        if (systemProperties.get(sp.getSystemPropertyName()) == null)%7B%0A                            spMissing = true;%0A                            break;%0A                        %7D%0A                    %7D%0A                %7D%0A                if(spMissing) %7B%0A    
             
@@ -4217,16 +4217,46 @@
 += %22%5Cn%5Cn
+A system property is missing. 
 Be sure 
@@ -4324,16 +4324,34 @@
 file%3E%22;%0A
+                %7D%0A
         

Check to see whether a sp is missing and not print if any input is missing