/*
 * Copyright Strimzi authors.
 * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
 */
package io.strimzi.operator.common.operator.resource;

import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.openshift.api.model.DeploymentConfig;
import io.fabric8.openshift.api.model.DeploymentConfigList;
import io.fabric8.openshift.api.model.DoneableDeploymentConfig;
import io.fabric8.openshift.client.OpenShiftClient;
import io.fabric8.openshift.client.dsl.DeployableScalableResource;
import io.vertx.core.Future;
import io.vertx.core.Vertx;

/**
 * Operations for {@code DeploymentConfigs}s.
 */
public class DeploymentConfigOperator extends AbstractScalableResourceOperator<OpenShiftClient, DeploymentConfig, DeploymentConfigList, DoneableDeploymentConfig, DeployableScalableResource<DeploymentConfig, DoneableDeploymentConfig>> {
    /**
     * Constructor
     * @param vertx The Vertx instance
     * @param client The Kubernetes client
     */
    public DeploymentConfigOperator(Vertx vertx, OpenShiftClient client) {
        super(vertx, client, "DeploymentConfig");
    }

    @Override
    protected MixedOperation<DeploymentConfig, DeploymentConfigList, DoneableDeploymentConfig, DeployableScalableResource<DeploymentConfig, DoneableDeploymentConfig>> operation() {
        return client.deploymentConfigs();
    }

    @Override
    protected Integer currentScale(String namespace, String name) {
        DeploymentConfig deploymentConfig = get(namespace, name);
        if (deploymentConfig != null) {
            return deploymentConfig.getSpec().getReplicas();
        } else {
            return null;
        }
    }

    @Override
    protected Future<ReconcileResult<DeploymentConfig>> internalPatch(String namespace, String name, DeploymentConfig current, DeploymentConfig desired) {
        desired.getSpec().getTemplate().getSpec().getContainers().get(0).setImage(current.getSpec().getTemplate().getSpec().getContainers().get(0).getImage());
        return super.internalPatch(namespace, name, current, desired);
    }

    /**
     * Asynchronously polls the deployment configuration until either the observed generation matches the desired
     * generation sequence number or timeout.
     *
     * @param namespace The namespace.
     * @param name The resource name.
     * @param pollIntervalMs The polling interval
     * @param timeoutMs The timeout
     * @return  A future which completes when the observed generation of the deployment configuration matches the
     * generation sequence number of the desired state.
     */
    public Future<Void> waitForObserved(String namespace, String name, long pollIntervalMs, long timeoutMs) {
        return waitFor(namespace, name, "observed", pollIntervalMs, timeoutMs, this::isObserved);
    }

    /**
     * Check if a deployment configuration has been observed.
     *
     * @param namespace The namespace.
     * @param name The resource name.
     * @return Whether the deployment has been observed.
     */
    private boolean isObserved(String namespace, String name) {
        DeploymentConfig dep = get(namespace, name);
        if (dep != null)   {
            return dep.getMetadata().getGeneration().equals(dep.getStatus().getObservedGeneration());
        } else {
            return false;
        }
    }
}

@@ -243,16 +243,75 @@
 ration;%0A
+import io.fabric8.openshift.api.model.DeploymentCondition;%0A
 import i
@@ -3254,16 +3254,538 @@
 ll)   %7B%0A
+            // Get the roll out status%0A            //     =%3E Sometimes it takes OCP some time before the generations are updated.%0A            //        So we need to check the conditions in addition to detect such situation.%0A            boolean rollOutNotStarting = true;%0A            DeploymentCondition progressing = getProgressingCondition(dep);%0A%0A            if (progressing != null)    %7B%0A                rollOutNotStarting = progressing.getReason() != null && !%22Unknown%22.equals(progressing.getStatus());%0A            %7D%0A%0A
         
@@ -3876,16 +3876,58 @@
 ation())
+%0A                    && rollOutNotStarting
 ;%0A      
@@ -3978,11 +3978,585 @@
  %7D%0A    %7D
+%0A%0A    /**%0A     * Retrieves the Progressing condition from the DeploymentConfig status%0A     *%0A     * @param dep   DeploymentConfig resource%0A     * @return      Progressing condition%0A     */%0A    private DeploymentCondition getProgressingCondition(DeploymentConfig dep)  %7B%0A        if (dep.getStatus() != null%0A                && dep.getStatus().getConditions() != null) %7B%0A            return dep.getStatus().getConditions().stream().filter(condition -%3E %22Progressing%22.equals(condition.getType())).findFirst().orElse(null);%0A        %7D else %7B%0A            return null;%0A        %7D%0A    %7D
 %0A%7D%0A

Fix waitForObserved for DeploymentConfigs to make the operator wait for roll outs (#2857)