// Copyright (C) 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.k8s.operator.receiver;

import com.google.gerrit.k8s.operator.cluster.GerritCluster;
import com.google.gerrit.k8s.operator.cluster.NfsWorkaroundConfig;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerPort;
import io.fabric8.kubernetes.api.model.Volume;
import io.fabric8.kubernetes.api.model.VolumeBuilder;
import io.fabric8.kubernetes.api.model.VolumeMount;
import io.fabric8.kubernetes.api.model.VolumeMountBuilder;
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.javaoperatorsdk.operator.api.reconciler.Context;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.CRUDKubernetesDependentResource;
import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@KubernetesDependent
public class ReceiverDeploymentDependentResource
    extends CRUDKubernetesDependentResource<Deployment, Receiver> {
  public static final int HTTP_PORT = 80;

  public ReceiverDeploymentDependentResource() {
    super(Deployment.class);
  }

  @Override
  protected Deployment desired(Receiver receiver, Context<Receiver> context) {
    GerritCluster gerritCluster =
        client
            .resources(GerritCluster.class)
            .inNamespace(receiver.getMetadata().getNamespace())
            .withName(receiver.getSpec().getCluster())
            .get();

    if (gerritCluster == null) {
      throw new IllegalStateException("The Gerrit cluster could not be found.");
    }

    DeploymentBuilder deploymentBuilder = new DeploymentBuilder();

    List<Container> initContainers = new ArrayList<>();

    NfsWorkaroundConfig nfsWorkaround =
        gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
    if (nfsWorkaround.isEnabled() && nfsWorkaround.isChownOnStartup()) {
      initContainers.add(gerritCluster.createNfsInitContainer());
    }

    deploymentBuilder
        .withApiVersion("apps/v1")
        .withNewMetadata()
        .withName(receiver.getMetadata().getName())
        .withNamespace(receiver.getMetadata().getNamespace())
        .withLabels(getLabels(gerritCluster, receiver))
        .endMetadata()
        .withNewSpec()
        .withReplicas(receiver.getSpec().getReplicas())
        .withNewStrategy()
        .withNewRollingUpdate()
        .withMaxSurge(receiver.getSpec().getMaxSurge())
        .withMaxUnavailable(receiver.getSpec().getMaxUnavailable())
        .endRollingUpdate()
        .endStrategy()
        .withNewSelector()
        .withMatchLabels(getLabels(gerritCluster, receiver))
        .endSelector()
        .withNewTemplate()
        .withNewMetadata()
        .withLabels(getLabels(gerritCluster, receiver))
        .endMetadata()
        .withNewSpec()
        .withTolerations(receiver.getSpec().getTolerations())
        .withTopologySpreadConstraints(receiver.getSpec().getTopologySpreadConstraints())
        .withAffinity(receiver.getSpec().getAffinity())
        .withPriorityClassName(receiver.getSpec().getPriorityClassName())
        .addAllToImagePullSecrets(gerritCluster.getSpec().getImagePullSecrets())
        .withNewSecurityContext()
        .withFsGroup(100L)
        .endSecurityContext()
        .addAllToInitContainers(initContainers)
        .addNewContainer()
        .withName("apache-git-http-backend")
        .withImagePullPolicy(gerritCluster.getSpec().getImagePullPolicy())
        .withImage(
            gerritCluster.getSpec().getGerritImages().getFullImageName("apache-git-http-backend"))
        .withEnv(GerritCluster.getPodNameEnvVar())
        .withPorts(getContainerPorts(receiver))
        .withResources(receiver.getSpec().getResources())
        .withReadinessProbe(receiver.getSpec().getReadinessProbe())
        .withLivenessProbe(receiver.getSpec().getLivenessProbe())
        .addAllToVolumeMounts(getVolumeMounts(receiver, gerritCluster, false))
        .endContainer()
        .addAllToVolumes(getVolumes(receiver, gerritCluster))
        .endSpec()
        .endTemplate()
        .endSpec();

    return deploymentBuilder.build();
  }

  public static Map<String, String> getLabels(GerritCluster gerritCluster, Receiver receiver) {
    return gerritCluster.getLabels(
        String.format("receiver-deployment-%s", receiver.getMetadata().getName()),
        ReceiverReconciler.class.getSimpleName());
  }

  private Set<Volume> getVolumes(Receiver receiver, GerritCluster gerritCluster) {
    Set<Volume> volumes = new HashSet<>();
    volumes.add(gerritCluster.getGitRepositoriesVolume());
    volumes.add(gerritCluster.getLogsVolume());

    volumes.add(
        new VolumeBuilder()
            .withName(receiver.getSpec().getCredentialSecretRef())
            .withNewSecret()
            .withSecretName(receiver.getSpec().getCredentialSecretRef())
            .endSecret()
            .build());

    NfsWorkaroundConfig nfsWorkaround =
        gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
    if (nfsWorkaround.isEnabled() && nfsWorkaround.getIdmapdConfig() != null) {
      volumes.add(gerritCluster.getNfsImapdConfigVolume());
    }

    return volumes;
  }

  private Set<VolumeMount> getVolumeMounts(
      Receiver receiver, GerritCluster gerritCluster, boolean isInitContainer) {
    Set<VolumeMount> volumeMounts = new HashSet<>();
    volumeMounts.add(gerritCluster.getGitRepositoriesVolumeMount("/var/gerrit/git"));
    volumeMounts.add(gerritCluster.getLogsVolumeMount("/var/log/apache2"));

    volumeMounts.add(
        new VolumeMountBuilder()
            .withName(receiver.getSpec().getCredentialSecretRef())
            .withMountPath("/var/apache/credentials/.htpasswd")
            .withSubPath(".htpasswd")
            .build());

    NfsWorkaroundConfig nfsWorkaround =
        gerritCluster.getSpec().getStorageClasses().getNfsWorkaround();
    if (nfsWorkaround.isEnabled() && nfsWorkaround.getIdmapdConfig() != null) {
      volumeMounts.add(gerritCluster.getNfsImapdConfigVolumeMount());
    }

    return volumeMounts;
  }

  private List<ContainerPort> getContainerPorts(Receiver receiver) {
    List<ContainerPort> containerPorts = new ArrayList<>();
    containerPorts.add(new ContainerPort(HTTP_PORT, null, null, "http", null));
    return containerPorts;
  }
}
