/*
 * Copyright 2018 Google, Inc.
 *
 * 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.netflix.spinnaker.clouddriver.kubernetes.v2.description.manifest;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.spinnaker.moniker.Moniker;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Optional;

@Slf4j
public class KubernetesManifestLabeler {
  private static final String KUBERNETES_LABEL = "kubernetes.io";
  private static final String APP_LABEL_PREFIX = "app." + KUBERNETES_LABEL;
  private static final String APP_NAME = APP_LABEL_PREFIX + "/name";
  private static final String APP_VERSION = APP_LABEL_PREFIX + "/version";
  private static final String APP_COMPONENT = APP_LABEL_PREFIX + "/component";
  private static final String APP_PART_OF = APP_LABEL_PREFIX + "/part-of";
  private static final String APP_MANAGED_BY = APP_LABEL_PREFIX + "/managed-by";

  private static ObjectMapper objectMapper = new ObjectMapper();

  private static void storeLabelAndOverwrite(Map<String, String> labels, String key, String value) {
    if (value == null) {
      return;
    }

    labels.put(key, value);
  }

  private static void storeLabel(Map<String, String> labels, String key, String value) {
    if (value == null) {
      return;
    }

    if (labels.containsKey(key)) {
      return;
    }

    labels.put(key, value);
  }

  public static void labelManifest(KubernetesManifest manifest, Moniker moniker) {
    Map<String, String> labels = manifest.getLabels();
    storeLabels(labels, moniker);

    manifest.getSpecTemplateLabels().flatMap(l -> {
      storeLabels(l, moniker);
      return Optional.empty();
    });
  }

  private static void storeLabels(Map<String, String> labels, Moniker moniker) {
    if (moniker == null) {
      return;
    }

    // other properties aren't currently set by Spinnaker
    storeLabel(labels, APP_NAME, moniker.getApp());
    storeLabelAndOverwrite(labels, APP_MANAGED_BY, "spinnaker");
  }

  public static KubernetesApplicationProperties getApplicationProperties(KubernetesManifest manifest) {
    Map<String, String> labels = manifest.getLabels();

    return new KubernetesApplicationProperties()
        .setName(labels.get(APP_NAME))
        .setVersion(labels.get(APP_VERSION))
        .setComponent(labels.get(APP_COMPONENT))
        .setPartOf(labels.get(APP_PART_OF))
        .setManagedBy(labels.get(APP_MANAGED_BY));
  }
}

@@ -902,16 +902,241 @@
 beler %7B%0A
+  private static final String SPINNAKER_LABEL = %22spinnaker.io%22;%0A  private static final String MONIKER_LABEL_PREFIX = %22moniker.%22 + SPINNAKER_LABEL;%0A  private static final String SEQUENCE = MONIKER_LABEL_PREFIX + %22/sequence%22;%0A%0A
   privat
@@ -2723,16 +2723,139 @@
 aker%22);%0A
+    if (moniker.getSequence() != null) %7B%0A      storeLabelAndOverwrite(labels, SEQUENCE, moniker.getSequence() + %22%22);%0A    %7D%0A
   %7D%0A%0A  p

apply sequence label (#3277)