// Copyright 2017 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.actions;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.TransitionMode;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.OS;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;

/** Action that writes a native {@code .exe} launcher for {java,sh,py}_binary rules on Windows. */
public final class LauncherFileWriteAction extends AbstractFileWriteAction {

  // Generated with /usr/bin/uuidgen.
  // This GUID doesn't have to be anything specific, we only use it to salt action cache keys so it
  // just has to be unique among other actions.
  private static final String GUID = "1f57afe7-f6f8-487c-9a8a-0a0286172fef";

  private final LaunchInfo launchInfo;
  private final Artifact launcher;

  /** Creates a new {@link LauncherFileWriteAction}, registering it with the {@code ruleContext}. */
  public static void createAndRegister(
      RuleContext ruleContext, Artifact output, LaunchInfo launchInfo) {
    ruleContext.registerAction(
        new LauncherFileWriteAction(
            ruleContext.getActionOwner(),
            output,
            ruleContext.getPrerequisiteArtifact("$launcher", TransitionMode.HOST),
            launchInfo));
  }

  /** Creates a new {@code LauncherFileWriteAction}. */
  private LauncherFileWriteAction(
      ActionOwner owner, Artifact output, Artifact launcher, LaunchInfo launchInfo) {
    super(
        owner,
        NestedSetBuilder.create(Order.STABLE_ORDER, Preconditions.checkNotNull(launcher)),
        output,
        /*makeExecutable=*/ true);
    this.launcher = launcher; // already null-checked in the superclass c'tor
    this.launchInfo = Preconditions.checkNotNull(launchInfo);
  }

  @Override
  public DeterministicWriter newDeterministicWriter(ActionExecutionContext ctx) {
    // TODO(laszlocsomor): make this code check for the execution platform, not the host platform,
    // once Bazel supports distinguishing between the two.
    // OS.getCurrent() returns the host platform, not the execution platform, which is fine in a
    // single-machine execution environment, but problematic with remote execution.
    Preconditions.checkState(OS.getCurrent() == OS.WINDOWS);
    return out -> {
      try (InputStream in = ctx.getInputPath(this.launcher).getInputStream()) {
        ByteStreams.copy(in, out);
      }
      long dataLength = this.launchInfo.write(out);
      ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
      buffer.order(ByteOrder.LITTLE_ENDIAN); // All Windows versions are little endian.
      buffer.putLong(dataLength);
      out.write(buffer.array());
      out.flush();
    };
  }

  @Override
  protected void computeKey(
      ActionKeyContext actionKeyContext,
      @Nullable ArtifactExpander artifactExpander,
      Fingerprint fp) {
    fp.addString(GUID);
    fp.addPath(this.launcher.getExecPath());
    fp.addString(this.launchInfo.fingerPrint);
  }

  /**
   * Metadata that describes the payload of the native launcher binary.
   *
   * <p>This object constructs the binary metadata lazily, to save memory.
   */
  public static final class LaunchInfo {

    /** Precomputed fingerprint of this object. */
    public final String fingerPrint;

    private final ImmutableList<Entry> entries;

    private LaunchInfo(ImmutableList<Entry> entries) {
      this.entries = entries;
      this.fingerPrint = computeKey(entries);
    }

    /** Creates a new {@link Builder}. */
    public static Builder builder() {
      return new Builder();
    }

    /** Writes this object's entries to {@code out}, returns the total written amount in bytes. */
    @VisibleForTesting
    long write(OutputStream out) throws IOException {
      long len = 0;
      for (Entry e : entries) {
        len += e.write(out);
        out.write('\0');
        ++len;
      }
      return len;
    }

    /** Computes the fingerprint of the {@code entries}. */
    private static String computeKey(ImmutableList<Entry> entries) {
      Fingerprint f = new Fingerprint();
      for (Entry e : entries) {
        e.addToFingerprint(f);
      }
      return f.hexDigestAndReset();
    }

    /** Writes {@code s} to {@code out} encoded as UTF-8, returns the written length in bytes. */
    private static long writeString(String s, OutputStream out) throws IOException {
      byte[] b = s.getBytes(StandardCharsets.UTF_8);
      out.write(b);
      return b.length;
    }

    /** Represents one entry in {@link LaunchInfo.entries}. */
    private static interface Entry {
      /** Writes this entry to {@code out}, returns the written length in bytes. */
      long write(OutputStream out) throws IOException;

      /** Adds this entry to the fingerprint computer {@code f}. */
      void addToFingerprint(Fingerprint f);
    }

    /** A key-value pair entry. */
    private static final class KeyValuePair implements Entry {
      private final String key;
      @Nullable private final String value;

      public KeyValuePair(String key, @Nullable String value) {
        this.key = Preconditions.checkNotNull(key);
        this.value = value;
      }

      @Override
      public long write(OutputStream out) throws IOException {
        long len = writeString(key, out);
        len += writeString("=", out);
        if (value != null && !value.isEmpty()) {
          len += writeString(value, out);
        }
        return len;
      }

      @Override
      public void addToFingerprint(Fingerprint f) {
        f.addString(key);
        f.addString(value != null ? value : "");
      }
    }

    /** A pair of a key and a delimiter-joined list of values. */
    private static final class JoinedValues implements Entry {
      private final String key;
      private final String delimiter;
      @Nullable private final Iterable<String> values;

      public JoinedValues(String key, String delimiter, @Nullable Iterable<String> values) {
        this.key = Preconditions.checkNotNull(key);
        this.delimiter = Preconditions.checkNotNull(delimiter);
        this.values = values;
      }

      @Override
      public long write(OutputStream out) throws IOException {
        long len = writeString(key, out);
        len += writeString("=", out);
        if (values != null) {
          boolean first = true;
          for (String v : values) {
            if (first) {
              first = false;
            } else {
              len += writeString(delimiter, out);
            }
            len += writeString(v, out);
          }
        }
        return len;
      }

      @Override
      public void addToFingerprint(Fingerprint f) {
        f.addString(key);
        if (values != null) {
          for (String v : values) {
            f.addString(v != null ? v : "");
          }
        }
      }
    }

    /** Builder for {@link LaunchInfo} instances. */
    public static final class Builder {
      private ImmutableList.Builder<Entry> entries = ImmutableList.builder();

      /** Builds a {@link LaunchInfo} from this builder. This builder may be reused. */
      public LaunchInfo build() {
        return new LaunchInfo(entries.build());
      }

      /**
       * Adds a key-value pair entry.
       *
       * <p>Examples:
       *
       * <ul>
       *   <li>{@code key} is "foo" and {@code value} is "bar", the written value is "foo=bar\0"
       *   <li>{@code key} is "foo" and {@code value} is null or empty, the written value is
       *       "foo=\0"
       * </ul>
       */
      public Builder addKeyValuePair(String key, @Nullable String value) {
        Preconditions.checkNotNull(key);
        if (!key.isEmpty()) {
          entries.add(new KeyValuePair(key, value));
        }
        return this;
      }

      /**
       * Adds a key and list of lazily-joined values.
       *
       * <p>Examples:
       *
       * <ul>
       *   <li>{@code key} is "foo", {@code delimiter} is ";", {@code values} is ["bar", "baz",
       *       "qux"], the written value is "foo=bar;baz;qux\0"
       *   <li>{@code key} is "foo", {@code delimiter} is irrelevant, {@code value} is null or
       *       empty, the written value is "foo=\0"
       * </ul>
       */
      public Builder addJoinedValues(
          String key, String delimiter, @Nullable Iterable<String> values) {
        Preconditions.checkNotNull(key);
        Preconditions.checkNotNull(delimiter);
        if (!key.isEmpty()) {
          entries.add(new JoinedValues(key, delimiter, values));
        }
        return this;
      }
    }
  }
}
