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