// Copyright 2018 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.repository;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.packages.BazelLibrary;
import com.google.devtools.build.lib.packages.BuildFileContainsErrorsException;
import com.google.devtools.build.lib.packages.NoSuchThingException;
import com.google.devtools.build.lib.rules.repository.ResolvedFileValue.ResolvedFileKey;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import com.google.devtools.build.lib.syntax.Mutability;
import com.google.devtools.build.lib.syntax.ParserInputSource;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/** Function computing the Starlark value of 'resolved' in a file. */
public class ResolvedFileFunction implements SkyFunction {

  @Override
  @Nullable
  public SkyValue compute(SkyKey skyKey, Environment env)
      throws InterruptedException, SkyFunctionException {

    ResolvedFileKey key = (ResolvedFileKey) skyKey;
    StarlarkSemantics starlarkSemantics = PrecomputedValue.STARLARK_SEMANTICS.get(env);
    if (starlarkSemantics == null) {
      return null;
    }
    FileValue fileValue = (FileValue) env.getValue(FileValue.key(key.getPath()));
    if (fileValue == null) {
      return null;
    }
    try {
      if (!fileValue.exists()) {
        throw new ResolvedFileFunctionException(
            new NoSuchThingException("Specified resolved file '" + key.getPath() + "' not found."));
      } else {
        byte[] bytes =
            FileSystemUtils.readWithKnownFileSize(
                key.getPath().asPath(), key.getPath().asPath().getFileSize());
        BuildFileAST ast =
            BuildFileAST.parseSkylarkFile(
                ParserInputSource.create(bytes, key.getPath().asPath().asFragment()),
                env.getListener());
        if (ast.containsErrors()) {
          throw new ResolvedFileFunctionException(
              new BuildFileContainsErrorsException(
                  LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                  "Failed to parse file resolved file " + key.getPath()));
        }
        com.google.devtools.build.lib.syntax.Environment resolvedEnvironment;
        try (Mutability mutability = Mutability.create("resolved file %s", key.getPath())) {
          resolvedEnvironment =
              com.google.devtools.build.lib.syntax.Environment.builder(mutability)
                  .setSemantics(starlarkSemantics)
                  .setGlobals(BazelLibrary.GLOBALS)
                  .build();
          if (!ast.exec(resolvedEnvironment, env.getListener())) {
            throw new ResolvedFileFunctionException(
                new BuildFileContainsErrorsException(
                    LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                    "Failed to evaluate resolved file " + key.getPath()));
          }
        }
        Object resolved = resolvedEnvironment.moduleLookup("resolved");
        if (resolved == null) {
          throw new ResolvedFileFunctionException(
              new BuildFileContainsErrorsException(
                  LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                  "Symbol 'resolved' not exported in resolved file " + key.getPath()));
        }
        if (!(resolved instanceof List)) {
          throw new ResolvedFileFunctionException(
              new BuildFileContainsErrorsException(
                  LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                  "Symbol 'resolved' in resolved file " + key.getPath() + " not a list"));
        }
        ImmutableList.Builder<Map<String, Object>> result
            = new ImmutableList.Builder<Map<String, Object>>();
        for (Object entry : (List) resolved) {
          if (!(entry instanceof Map)) {
            throw new ResolvedFileFunctionException(
                new BuildFileContainsErrorsException(
                    LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                    "Symbol 'resolved' in resolved file "
                        + key.getPath()
                        + " contains a non-map entry"));
          }
          ImmutableMap.Builder<String, Object> entryBuilder
              = new ImmutableMap.Builder<String, Object>();
          for (Map.Entry<Object, Object> keyValue : ((Map<Object, Object>) entry).entrySet()) {
            Object attribute = keyValue.getKey();
            if (!(attribute instanceof String)) {
              throw new ResolvedFileFunctionException(
                  new BuildFileContainsErrorsException(
                      LabelConstants.EXTERNAL_PACKAGE_IDENTIFIER,
                      "Symbol 'resolved' in resolved file "
                          + key.getPath()
                          + " contains a non-string key in one of its entries"));
            }
            entryBuilder.put((String) attribute, keyValue.getValue());
          }
          result.add(entryBuilder.build());
        }
        return new ResolvedFileValue(result.build());
      }
    } catch (IOException e) {
      throw new ResolvedFileFunctionException(e);
    }
  }

  @Override
  @Nullable
  public String extractTag(SkyKey skyKey) {
    return null;
  }

  private static final class ResolvedFileFunctionException extends SkyFunctionException {
    ResolvedFileFunctionException(IOException e) {
      super(e, SkyFunctionException.Transience.PERSISTENT);
    }

    ResolvedFileFunctionException(NoSuchThingException e) {
      super(e, SkyFunctionException.Transience.PERSISTENT);
    }
  }
}
