// 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.rules.java;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoCollection;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.rules.java.WriteBuildInfoPropertiesAction.TimestampFormatter;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * Java build info creation - generates properties file that contain the corresponding build-info
 * data.
 */
public abstract class JavaBuildInfoFactory implements BuildInfoFactory {
  public static final BuildInfoKey KEY = new BuildInfoKey("Java");

  static final PathFragment BUILD_INFO_NONVOLATILE_PROPERTIES_NAME =
      PathFragment.create("build-info-nonvolatile.properties");
  static final PathFragment BUILD_INFO_VOLATILE_PROPERTIES_NAME =
      PathFragment.create("build-info-volatile.properties");
  static final PathFragment BUILD_INFO_REDACTED_PROPERTIES_NAME =
      PathFragment.create("build-info-redacted.properties");

  private static final DateTimeFormatter DEFAULT_TIME_FORMAT =
      DateTimeFormatter.ofPattern("EEE MMM d HH:mm:ss yyyy");

  // A default formatter that returns a date in UTC format.
  @AutoCodec
  @VisibleForSerialization
  static class DefaultTimestampFormatter implements TimestampFormatter {
    @Override
    public String format(long timestamp) {
      return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.UTC).format(DEFAULT_TIME_FORMAT)
          + " ("
          + timestamp / 1000
          + ')';
    }
  }

  private static final TimestampFormatter DEFAULT_FORMATTER = new DefaultTimestampFormatter();

  @Override
  public final BuildInfoCollection create(
      BuildInfoContext context,
      BuildConfiguration config,
      Artifact stableStatus,
      Artifact volatileStatus,
      RepositoryName repositoryName) {
    WriteBuildInfoPropertiesAction redactedInfo =
        getHeader(
            context,
            config,
            BUILD_INFO_REDACTED_PROPERTIES_NAME,
            NestedSetBuilder.emptySet(Order.STABLE_ORDER),
            createRedactedTranslator(),
            true,
            true,
            repositoryName);
    WriteBuildInfoPropertiesAction nonvolatileInfo =
        getHeader(
            context,
            config,
            BUILD_INFO_NONVOLATILE_PROPERTIES_NAME,
            NestedSetBuilder.create(Order.STABLE_ORDER, stableStatus),
            createNonVolatileTranslator(),
            false,
            true,
            repositoryName);
    WriteBuildInfoPropertiesAction volatileInfo =
        getHeader(
            context,
            config,
            BUILD_INFO_VOLATILE_PROPERTIES_NAME,
            NestedSetBuilder.create(Order.STABLE_ORDER, volatileStatus),
            createVolatileTranslator(),
            true,
            false,
            repositoryName);
    List<Action> actions = new ArrayList<>(3);
    actions.add(redactedInfo);
    actions.add(nonvolatileInfo);
    actions.add(volatileInfo);
    return new BuildInfoCollection(
        actions,
        ImmutableList.of(nonvolatileInfo.getPrimaryOutput(), volatileInfo.getPrimaryOutput()),
        ImmutableList.of(redactedInfo.getPrimaryOutput()));
  }

  /** Creates a {@link BuildInfoPropertiesTranslator} to use for volatile keys. */
  protected abstract BuildInfoPropertiesTranslator createVolatileTranslator();

  /** Creates a {@link BuildInfoPropertiesTranslator} to use for non-volatile keys. */
  protected abstract BuildInfoPropertiesTranslator createNonVolatileTranslator();

  /**
   * Creates a {@link BuildInfoPropertiesTranslator} to use for redacted version of the build
   * informations.
   */
  protected abstract BuildInfoPropertiesTranslator createRedactedTranslator();

  /** Specifies the {@link TimestampFormatter} to use to output dates in the properties file. */
  protected TimestampFormatter getTimestampFormatter() {
    return DEFAULT_FORMATTER;
  }

  private WriteBuildInfoPropertiesAction getHeader(
      BuildInfoContext context,
      BuildConfiguration config,
      PathFragment propertyFileName,
      NestedSet<Artifact> inputs,
      BuildInfoPropertiesTranslator translator,
      boolean includeVolatile,
      boolean includeNonVolatile,
      RepositoryName repositoryName) {
    ArtifactRoot outputPath = config.getIncludeDirectory(repositoryName);
    final Artifact output =
        context.getBuildInfoArtifact(
            propertyFileName,
            outputPath,
            includeVolatile && !inputs.isEmpty()
                ? BuildInfoType.NO_REBUILD
                : BuildInfoType.FORCE_REBUILD_IF_CHANGED);
    return new WriteBuildInfoPropertiesAction(
        inputs, output, translator, includeVolatile, includeNonVolatile, getTimestampFormatter());
  }

  @Override
  public final BuildInfoKey getKey() {
    return KEY;
  }

  @Override
  public boolean isEnabled(BuildConfiguration config) {
    return config.hasFragment(JavaConfiguration.class);
  }
}
