package com.hubspot.singularity.scheduler;

import com.hubspot.singularity.CanaryDeploySettings;
import com.hubspot.singularity.SingularityDeploy;
import com.hubspot.singularity.SingularityDeployProgress;
import com.hubspot.singularity.SingularityRequest;
import com.hubspot.singularity.SingularityTaskId;
import com.hubspot.singularity.SingularityUpdatePendingDeployRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

public class CanaryDeployHelper {

  public static List<SingularityTaskId> tasksToShutDown(
    SingularityDeployProgress deployProgress,
    Collection<SingularityTaskId> otherActiveTasks,
    SingularityRequest request
  ) {
    int numTasksToShutDown = Math.max(
      otherActiveTasks.size() -
      (request.getInstancesSafe() - deployProgress.getTargetActiveInstances()),
      0
    );
    List<SingularityTaskId> sortedOtherTasks = new ArrayList<>(otherActiveTasks);
    sortedOtherTasks.sort(SingularityTaskId.INSTANCE_NO_COMPARATOR);
    return sortedOtherTasks.isEmpty()
      ? sortedOtherTasks
      : sortedOtherTasks.subList(
        0,
        Math.min(numTasksToShutDown, sortedOtherTasks.size())
      );
  }

  public static int getNewTargetInstances(
    SingularityDeployProgress deployProgress,
    SingularityRequest request,
    Optional<SingularityUpdatePendingDeployRequest> updateRequest,
    CanaryDeploySettings canaryDeploySettings
  ) {
    // TODO - Use canary cycle count here
    return updateRequest
      .map(
        singularityUpdatePendingDeployRequest ->
          Math.min(
            singularityUpdatePendingDeployRequest.getTargetActiveInstances(),
            request.getInstancesSafe()
          )
      )
      .orElseGet(
        () ->
          Math.min(
            deployProgress.getTargetActiveInstances() +
            canaryDeploySettings.getInstanceGroupSize(),
            request.getInstancesSafe()
          )
      );
  }

  public static boolean canRetryTasks(
    SingularityDeploy deploy,
    Collection<SingularityTaskId> inactiveDeployMatchingTasksForInstanceGroup
  ) {
    int maxFailures = deploy.getCanaryDeploySettings().getAllowedTasksFailuresPerGroup();
    return (
      maxFailures > 0 && inactiveDeployMatchingTasksForInstanceGroup.size() <= maxFailures
    );
  }
}

@@ -1449,50 +1449,8 @@
 ) %7B%0A
-    // TODO - Use canary cycle count here%0A
     
@@ -1470,16 +1470,16 @@
 Request%0A
+
       .m
@@ -1719,16 +1719,18 @@
    () -%3E
+ %7B
 %0A       
@@ -1724,32 +1724,409 @@
  -%3E %7B%0A          
+int cycleCount =%0A            deployProgress.getTargetActiveInstances() /%0A            canaryDeploySettings.getAllowedTasksFailuresPerGroup();%0A          if (cycleCount %3E= canaryDeploySettings.getCanaryCycleCount()) %7B%0A            // We have run enough canary cycles, launch everything remaining%0A            return request.getInstancesSafe();%0A          %7D else %7B%0A            return 
 Math.min(%0A      
@@ -2111,32 +2111,34 @@
 eturn Math.min(%0A
+  
             depl
@@ -2181,32 +2181,34 @@
 ) +%0A            
+  
 canaryDeploySett
@@ -2232,24 +2232,26 @@
 roupSize(),%0A
+  
             
@@ -2279,33 +2279,58 @@
 afe()%0A          
-)
+  );%0A          %7D%0A        %7D
 %0A      );%0A  %7D%0A%0A 

use canary cycle count