// 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.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, 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;
      }
    }
  }
}
