// Copyright 2021 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.worker;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.WorkerMetrics;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Contains data about worker statistics during execution. This class contains data for {@link
 * com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildMetrics.WorkerMetrics}
 */
public class WorkerProcessMetrics {

  private final List<Integer> workerIds;

  private final long processId;

  private final String mnemonic;

  private final boolean isMultiplex;

  private final boolean isSandbox;

  private boolean isMeasurable = false;

  private final int workerKeyHash;

  private int memoryInKb = 0;

  private Optional<Instant> lastCallTime = Optional.empty();

  private Optional<Instant> lastCollectedTime = Optional.empty();

  private final WorkerProcessStatus status;

  private boolean newlyCreated = true;
  private final AtomicInteger actionsExecuted = new AtomicInteger(0);

  public WorkerProcessMetrics(
      List<Integer> workerIds,
      long processId,
      WorkerProcessStatus status,
      String mnemonic,
      boolean isMultiplex,
      boolean isSandbox,
      int workerKeyHash) {
    this.workerIds = workerIds;
    this.processId = processId;
    this.status = status;
    this.mnemonic = mnemonic;
    this.isMultiplex = isMultiplex;
    this.isSandbox = isSandbox;
    this.workerKeyHash = workerKeyHash;
  }

  public WorkerProcessMetrics(
      int workerId,
      long processId,
      WorkerProcessStatus status,
      String mnemonic,
      boolean isMultiplex,
      boolean isSandbox,
      int workerKeyHash) {
    this(
        new ArrayList<>(Arrays.asList(workerId)),
        processId,
        status,
        mnemonic,
        isMultiplex,
        isSandbox,
        workerKeyHash);
  }

  public void maybeAddWorkerId(int workerId, WorkerProcessStatus status) {
    // Multiplex workers have multiple worker ids, make sure not to include duplicate worker ids.
    if (workerIds.contains(workerId)) {
      return;
    }
    workerIds.add(workerId);
  }

  public void addCollectedMetrics(int memoryInKb, Instant collectionTime) {
    this.memoryInKb = memoryInKb;
    this.isMeasurable = true;
    this.lastCollectedTime = Optional.of(collectionTime);
  }

  /** Reset relevant internal states before each command. */
  public void onBeforeCommand() {
    newlyCreated = false;
  }

  /** Whether the worker process was created during the current invocation. */
  public boolean isNewlyCreated() {
    return newlyCreated;
  }

  public void incrementActionsExecuted() {
    actionsExecuted.incrementAndGet();
  }

  public int getActionsExecuted() {
    return actionsExecuted.get();
  }

  public Optional<Instant> getLastCallTime() {
    return lastCallTime;
  }

  public Optional<Instant> getLastCollectedTime() {
    return lastCollectedTime;
  }

  public void setLastCallTime(Instant lastCallTime) {
    this.lastCallTime = Optional.of(lastCallTime);
  }

  public boolean isMeasurable() {
    return isMeasurable;
  }

  public ImmutableList<Integer> getWorkerIds() {
    return ImmutableList.copyOf(workerIds);
  }

  public long getProcessId() {
    return processId;
  }

  public String getMnemonic() {
    return mnemonic;
  }

  public boolean isMultiplex() {
    return isMultiplex;
  }

  public boolean isSandboxed() {
    return isSandbox;
  }

  public int getWorkerKeyHash() {
    return workerKeyHash;
  }

  public int getUsedMemoryInKb() {
    return memoryInKb;
  }

  public WorkerProcessStatus getStatus() {
    return status;
  }

  public WorkerMetrics toProto() {
    WorkerMetrics.WorkerStats.Builder statsBuilder =
        WorkerMetrics.WorkerStats.newBuilder().setWorkerMemoryInKb(memoryInKb);
    if (lastCollectedTime.isPresent()) {
      statsBuilder.setCollectTimeInMs(lastCollectedTime.get().toEpochMilli());
    }
    if (lastCallTime.isPresent()) {
      statsBuilder.setLastActionStartTimeInMs(lastCallTime.get().toEpochMilli());
    }

    return WorkerMetrics.newBuilder()
        .addAllWorkerIds(workerIds)
        .setProcessId((int) processId)
        .setMnemonic(mnemonic)
        .setIsSandbox(isSandbox)
        .setIsMultiplex(isMultiplex)
        .setIsMeasurable(isMeasurable)
        .setWorkerKeyHash(workerKeyHash)
        .setWorkerStatus(status.toWorkerStatus())
        .setActionsExecuted(actionsExecuted.get())
        .addWorkerStats(statsBuilder.build())
        .build();
  }
}
