// Copyright 2019 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.platform;

import build.bazel.remote.execution.v2.Platform;
import build.bazel.remote.execution.v2.Platform.Property;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.UserExecException;
import com.google.devtools.build.lib.remote.options.RemoteOptions;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.server.FailureDetails.Spawn.Code;
import com.google.protobuf.TextFormat;
import com.google.protobuf.TextFormat.ParseException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import javax.annotation.Nullable;

/** Utilities for accessing platform properties. */
public final class PlatformUtils {

  private static void sortPlatformProperties(Platform.Builder builder) {
    List<Platform.Property> properties =
        Ordering.from(Comparator.comparing(Platform.Property::getName))
            .sortedCopy(builder.getPropertiesList());
    builder.clearProperties();
    builder.addAllProperties(properties);
  }

  @Nullable
  public static Platform buildPlatformProto(Map<String, String> executionProperties) {
    if (executionProperties.isEmpty()) {
      return null;
    }
    Platform.Builder builder = Platform.newBuilder();
    for (Map.Entry<String, String> keyValue : executionProperties.entrySet()) {
      Property property =
          Property.newBuilder().setName(keyValue.getKey()).setValue(keyValue.getValue()).build();
      builder.addProperties(property);
    }

    sortPlatformProperties(builder);
    return builder.build();
  }

  @Nullable
  public static Platform getPlatformProto(Spawn spawn, @Nullable RemoteOptions remoteOptions)
      throws UserExecException {
    return getPlatformProto(spawn, remoteOptions, ImmutableMap.of());
  }

  @Nullable
  public static Platform getPlatformProto(
      Spawn spawn, @Nullable RemoteOptions remoteOptions, Map<String, String> additionalProperties)
      throws UserExecException {
    SortedMap<String, String> defaultExecProperties =
        remoteOptions != null
            ? remoteOptions.getRemoteDefaultExecProperties()
            : ImmutableSortedMap.of();

    if (spawn.getExecutionPlatform() == null
        && spawn.getCombinedExecProperties().isEmpty()
        && defaultExecProperties.isEmpty()
        && additionalProperties.isEmpty()) {
      return null;
    }

    Map<String, String> properties;
    if (!spawn.getCombinedExecProperties().isEmpty()) {
      // Apply default exec properties if the execution platform does not already set
      // exec_properties
      if (spawn.getExecutionPlatform() == null
          || spawn.getExecutionPlatform().execProperties().isEmpty()) {
        properties = new HashMap<>();
        properties.putAll(defaultExecProperties);
        properties.putAll(spawn.getCombinedExecProperties());
      } else {
        properties = spawn.getCombinedExecProperties();
      }
    } else if (spawn.getExecutionPlatform() != null
        && !Strings.isNullOrEmpty(spawn.getExecutionPlatform().remoteExecutionProperties())) {
      properties = new HashMap<>();
      // Try and get the platform info from the execution properties.
      try {
        Platform.Builder platformBuilder = Platform.newBuilder();
        TextFormat.getParser()
            .merge(spawn.getExecutionPlatform().remoteExecutionProperties(), platformBuilder);
        for (Property property : platformBuilder.getPropertiesList()) {
          properties.put(property.getName(), property.getValue());
        }
      } catch (ParseException e) {
        String message =
            String.format(
                "Failed to parse remote_execution_properties from platform %s",
                spawn.getExecutionPlatform().label());
        throw new UserExecException(
            e, createFailureDetail(message, Code.INVALID_REMOTE_EXECUTION_PROPERTIES));
      }
    } else {
      properties = defaultExecProperties;
    }

    if (!additionalProperties.isEmpty()) {
      if (properties.isEmpty()) {
        properties = additionalProperties;
      } else {
        // Merge the two maps.
        properties = new HashMap<>(properties);
        properties.putAll(additionalProperties);
      }
    }

    Platform.Builder platformBuilder = Platform.newBuilder();
    for (Map.Entry<String, String> entry : properties.entrySet()) {
      platformBuilder.addPropertiesBuilder().setName(entry.getKey()).setValue(entry.getValue());
    }
    sortPlatformProperties(platformBuilder);
    return platformBuilder.build();
  }

  private static FailureDetail createFailureDetail(String message, Code detailedCode) {
    return FailureDetail.newBuilder()
        .setMessage(message)
        .setSpawn(FailureDetails.Spawn.newBuilder().setCode(detailedCode))
        .build();
  }
}
