// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.analysis;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.flogger.GoogleLogger;
import java.util.Date;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/**
 * Determines the version information of the current process.
 *
 * <p>The version information is a dictionary mapping from string keys to string values.  For
 * build stamping, it should have the key "Build label", which contains among others a
 * XXXXXXX-YYYY.MM.DD string to indicate the version of the release.  If no data is available
 * (eg. when running non-released version), {@link #isAvailable()} returns false.
 */
public class BlazeVersionInfo {
  public static final String BUILD_LABEL = "Build label";
  /** Key for the release timestamp is seconds. */
  public static final String BUILD_TIMESTAMP = "Build timestamp as int";

  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private static BlazeVersionInfo instance = null;

  private final Map<String, String> buildData = Maps.newTreeMap();

  public BlazeVersionInfo(Map<String, String> info) {
    buildData.putAll(info);
  }

  /**
   * Accessor method for BlazeVersionInfo singleton.
   *
   * <p>If setBuildInfo was not called, returns an empty BlazeVersionInfo instance, which should
   * not be persisted.
   */
  public static synchronized BlazeVersionInfo instance() {
    if (instance == null) {
      return new BlazeVersionInfo(ImmutableMap.<String, String>of());
    }
    return instance;
  }

  private static void logVersionInfo(BlazeVersionInfo info) {
    if (info.getSummary() == null) {
      logger.atWarning().log("Bazel release version information not available");
    } else {
      logger.atInfo().log("Bazel version info: %s", info.getSummary());
    }
  }

  /**
   * Sets build info.
   *
   * <p>This should be called once in the program execution, as early soon as possible, so we
   * can have the version information even before modules are initialized.
   */
  public static synchronized void setBuildInfo(Map<String, String> info) {
    if (instance != null) {
      throw new IllegalStateException("setBuildInfo called twice.");
    }
    instance = new BlazeVersionInfo(info);
    logVersionInfo(instance);
  }

  /**
   * Indicates whether version information is available.
   */
  public boolean isAvailable() {
    return !buildData.isEmpty();
  }

  /**
   * Returns the summary which gets displayed in the 'version' command. The summary is a list of
   * formatted key / value pairs.
   */
  @Nullable
  public String getSummary() {
    if (buildData.isEmpty()) {
      return null;
    }
    return buildData.entrySet().stream()
        .map(e -> e.getKey() + ": " + e.getValue())
        .collect(Collectors.joining("\n"));
  }

  /**
   * Returns true iff this binary is released--that is, a
   * binary built with a release label.
   */
  public boolean isReleasedBlaze() {
    String buildLabel = buildData.get(BUILD_LABEL);
    return buildLabel != null && buildLabel.length() > 0;
  }

  /**
   * Returns the release label, if any, or "development version".
   */
  public String getReleaseName() {
    String buildLabel = buildData.get(BUILD_LABEL);
    return (buildLabel != null && buildLabel.length() > 0)
        ? "release " + buildLabel
        : "development version";
  }

  /**
   * Returns the version, if any, or {@code ""}. The returned version number is easier to process
   * than the version returned by #getReleaseName().
   */
  public String getVersion() {
    String buildLabel = buildData.get(BUILD_LABEL);
    return buildLabel != null ? buildLabel : "";
  }

  /**
   * Returns the release timestamp in seconds.
   */
  public long getTimestamp() {
    String timestamp = buildData.get(BUILD_TIMESTAMP);
    if (timestamp == null || timestamp.equals("0")) {
      return new Date().getTime();
    }
    return Long.parseLong(timestamp);
  }

  @VisibleForTesting
  public Map<String, String> getBuildData() {
    return buildData;
  }
}
