package net.hawkengine.core.components.pipelinescheduler;

import net.hawkengine.model.Job;
import net.hawkengine.model.Pipeline;
import net.hawkengine.model.Stage;
import net.hawkengine.model.enums.JobStatus;
import net.hawkengine.model.enums.StageStatus;
import net.hawkengine.model.enums.Status;
import net.hawkengine.services.PipelineService;
import net.hawkengine.services.interfaces.IPipelineService;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.stream.Collectors;

public class StatusUpdaterService extends Thread {
    private IPipelineService pipelineService;
    private static final Logger logger = Logger.getLogger(StatusUpdaterService.class.getName());

    public StatusUpdaterService() {
        this.pipelineService = new PipelineService();
    }

    public StatusUpdaterService(IPipelineService pipelineService) {
        this.pipelineService = pipelineService;
    }

    public void updateStatuses() {
        List<Pipeline> pipelinesInProgress = this.getAllPipelinesInProgress();
        for (Pipeline pipeline : pipelinesInProgress) {
            this.updateAllStatuses(pipeline);
            this.pipelineService.update(pipeline);
        }
    }

    public List<Pipeline> getAllPipelinesInProgress() {
        List<Pipeline> allPipelines = (List<Pipeline>) this.pipelineService
                .getAll()
                .getObject();

        List<Pipeline> pipelinesInProgress = allPipelines
                .stream()
                .filter(p -> p.getStatus() == Status.IN_PROGRESS)
                .collect(Collectors.toList());

        return pipelinesInProgress;
    }

    public boolean updateAllStatuses(Object pipeline) {
        Stack stack = new Stack();
        stack.push(pipeline);

        while (!stack.isEmpty()) {
            Object node = stack.pop();
            if (node.getClass() == Job.class) {
                Pipeline pipelineToUpdate = (Pipeline) pipeline;
                this.updatePipelineStatus(pipelineToUpdate);
                return true;
            }

            if (node.getClass() == Pipeline.class) {
                Pipeline pipelineNode = (Pipeline) node;
                stack.addAll(pipelineNode.getStages());
                this.updateStageStatusesInSequence(pipelineNode.getStages());
            } else {
                Stage stageNode = (Stage) node;
                stack.addAll(stageNode.getJobs());
                this.updateStageStatus(stageNode);
            }
        }

        return false;
    }

    public void updateStageStatusesInSequence(List<Stage> stages){
        int stagesCollectionSize = stages.size();
        for (Stage currentStage : stages) {
            if (currentStage.getStatus() == StageStatus.NOT_RUN) {
                currentStage.setStatus(StageStatus.IN_PROGRESS);
                continue;
            } else if (currentStage.getStatus() == StageStatus.PASSED) {
                continue;
            } else {
                break;
            }
        }
    }

    public void updateStageStatus(Stage stage) {
        List<JobStatus> jobStatuses = new ArrayList<>();
        List<Job> jobs = stage.getJobs();

        for (Job job : jobs) {
            JobStatus jobStatus = job.getStatus();
            jobStatuses.add(jobStatus);
        }

        if (jobStatuses.contains(JobStatus.FAILED)) {
            stage.setStatus(StageStatus.FAILED);
        } else if (this.areAllPassed(jobStatuses)) {
            stage.setStatus(StageStatus.PASSED);
        }
    }

    public void updatePipelineStatus(Pipeline pipeline) {
        List<Stage> stages = pipeline.getStages();
        List<Status> stageStatuses = new ArrayList<>();

        for (Stage stage : stages) {
            StageStatus stageStatus = stage.getStatus();
            //stageStatuses.add(stageStatus);
        }

        if (stageStatuses.contains(Status.FAILED)) {
            pipeline.setStatus(Status.FAILED);
        } else if (this.areAllPassed(stageStatuses)) {
            pipeline.setStatus(Status.PASSED);
        }
    }

    public boolean areAllPassed(List<?> statuses) {
        String[] statusesAsString = new String[statuses.size()];
        int index = 0;

        for (Object status : statuses) {
            statusesAsString[index] = status.toString();
            index++;
        }

        for (String aStatusesAsString : statusesAsString) {
            if (!aStatusesAsString.equals("PASSED")) {
                return false;
            }
        }

        return true;
    }
}

@@ -454,64 +454,9 @@
 til.
-ArrayList;%0Aimport java.util.List;%0Aimport java.util.Stack
+*
 ;%0Aim
@@ -545,54 +545,8 @@
 d %7B%0A
-    private IPipelineService pipelineService;%0A
     
@@ -633,24 +633,70 @@
 .getName());
+%0A    private IPipelineService pipelineService;
 %0A%0A    public
@@ -1687,31 +1687,123 @@
     
-Stack stack = new Stack
+Pipeline pipelineToUpdate = null;%0A        Stack stack = new Stack();%0A        Queue%3CObject%3E queue = new LinkedList%3C%3E
 ();%0A
@@ -1831,16 +1831,45 @@
 peline);
+%0A        queue.add(pipeline);
 %0A%0A      
@@ -1940,37 +1940,87 @@
 ();%0A            
-if (n
+Object queueNode = queue.poll();%0A            if (queueN
 ode.getClass() =
@@ -2046,33 +2046,24 @@
             
-Pipeline 
 pipelineToUp
@@ -2211,17 +2211,22 @@
     if (
-n
+queueN
 ode.getC
@@ -2269,33 +2269,24 @@
         
-Pipeline 
 pipeline
 Node = (
@@ -2277,19 +2277,23 @@
 pipeline
-Nod
+ToUpdat
 e = (Pip
@@ -2299,17 +2299,22 @@
 peline) 
-n
+queueN
 ode;%0A   
@@ -2339,35 +2339,39 @@
 .addAll(pipeline
-Nod
+ToUpdat
 e.getStages());%0A
@@ -2390,42 +2390,20 @@
     
-this.updateStageStatusesInSequence
+queue.addAll
 (pip
@@ -2407,19 +2407,23 @@
 pipeline
-Nod
+ToUpdat
 e.getSta
@@ -2493,17 +2493,22 @@
 (Stage) 
-n
+queueN
 ode;%0A   
@@ -2575,40 +2575,122 @@
     
-this.updateStageStatus(stageNode
+queue.addAll(stageNode.getJobs());%0A                this.updateStageStatusesInSequence(pipelineToUpdate.getStages()
 );%0A 
@@ -2807,16 +2807,17 @@
  stages)
+ 
 %7B%0A      
@@ -2896,32 +2896,82 @@
 age : stages) %7B%0A
+            this.updateStageStatus(currentStage);%0A
             if (
@@ -3098,32 +3098,29 @@
             
-continue
+break
 ;%0A          
@@ -3909,16 +3909,21 @@
    List%3C
+Stage
 Status%3E 
@@ -4068,10 +4068,8 @@
     
-//
 stag
@@ -4142,16 +4142,21 @@
 ontains(
+Stage
 Status.F

Update Stage Statuses modified #11