/*******************************************************************************
 * (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.systemtests;

import com.google.common.collect.Sets;
import io.cloudslang.lang.api.Slang;
import io.cloudslang.lang.entities.CompilationArtifact;
import io.cloudslang.lang.entities.ScoreLangConstants;
import io.cloudslang.lang.runtime.events.LanguageEventData;
import io.cloudslang.score.events.ScoreEvent;
import io.cloudslang.score.events.ScoreEventListener;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class TriggerFlows {

    private final static HashSet<String> FINISHED_EVENTS =
            Sets.newHashSet(ScoreLangConstants.EVENT_EXECUTION_FINISHED, ScoreLangConstants.SLANG_EXECUTION_EXCEPTION);

    private final static HashSet<String> STEP_EVENTS =
            Sets.newHashSet(ScoreLangConstants.EVENT_INPUT_END, ScoreLangConstants.EVENT_OUTPUT_END);

    private final static HashSet<String> BRANCH_EVENTS = Sets.newHashSet(ScoreLangConstants.EVENT_BRANCH_END);

    private final static HashSet<String> ASYNC_LOOP_EVENTS = Sets.newHashSet(ScoreLangConstants.EVENT_ASYNC_LOOP_OUTPUT_END);

    @Autowired
    private Slang slang;

    public ScoreEvent runSync(
            CompilationArtifact compilationArtifact,
            Map<String, ? extends Serializable> userInputs,
            Map<String, ? extends Serializable> systemProperties) {
        final BlockingQueue<ScoreEvent> finishEvent = new LinkedBlockingQueue<>();
        ScoreEventListener finishListener = new ScoreEventListener() {
            @Override
            public void onEvent(ScoreEvent event) throws InterruptedException {
                finishEvent.add(event);
            }
        };
        slang.subscribeOnEvents(finishListener, FINISHED_EVENTS);

        slang.run(compilationArtifact, userInputs, systemProperties);

        try {
            ScoreEvent event = finishEvent.take();
            if (event.getEventType().equals(ScoreLangConstants.SLANG_EXECUTION_EXCEPTION)){
                LanguageEventData languageEvent = (LanguageEventData) event.getData();
                throw new RuntimeException((String) languageEvent.get(LanguageEventData.EXCEPTION));
            }
            slang.unSubscribeOnEvents(finishListener);
            return event;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public RuntimeInformation runWithData(CompilationArtifact compilationArtifact, Map<String, ? extends Serializable> userInputs, Map<String, ? extends Serializable> systemProperties) {
        RunDataAggregatorListener runDataAggregatorListener = new RunDataAggregatorListener();
        slang.subscribeOnEvents(runDataAggregatorListener, STEP_EVENTS);

        BranchAggregatorListener branchAggregatorListener = new BranchAggregatorListener();
        slang.subscribeOnEvents(branchAggregatorListener, BRANCH_EVENTS);

        JoinAggregatorListener joinAggregatorListener = new JoinAggregatorListener();
        slang.subscribeOnEvents(joinAggregatorListener, ASYNC_LOOP_EVENTS);

        try {
            Thread.sleep(0);      // TODO : remove this! when it is not here tests fail for some reason
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        runSync(compilationArtifact, userInputs, systemProperties);

        Map<String, StepData> tasks = runDataAggregatorListener.aggregate();
        Map<String, List<StepData>> branchesByPath = branchAggregatorListener.aggregate();
        Map<String, StepData> asyncTasks = joinAggregatorListener.aggregate();

        RuntimeInformation runtimeInformation = new RuntimeInformation(tasks, branchesByPath, asyncTasks);

        slang.unSubscribeOnEvents(joinAggregatorListener);
        slang.unSubscribeOnEvents(branchAggregatorListener);
        slang.unSubscribeOnEvents(runDataAggregatorListener);

        return runtimeInformation;
    }

}

@@ -3709,17 +3709,21 @@
 d.sleep(
-0
+2000L
 );      
@@ -3723,17 +3723,17 @@
 ;      /
-/
+*
  TODO : 
@@ -3749,54 +3749,48 @@
 is! 
-when it is not here tests fail for some reason
+only to test unstable navigation tests*/
 %0A   
@@ -3869,24 +3869,24 @@
 %0A        %7D%0A%0A
-
         runS
@@ -3934,32 +3934,234 @@
 emProperties);%0A%0A
+        try %7B%0A            Thread.sleep(2000L);     /* TODO : remove this! only to test unstable navigation tests*/%0A        %7D catch (InterruptedException e) %7B%0A            e.printStackTrace();%0A        %7D%0A%0A
         Map%3CStri

revert for now - sry i tried to handle it