// 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.skydoc.rendering;

import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AspectInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ProviderInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.StarlarkFunctionInfo;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import net.starlark.java.eval.StarlarkFunction;

/** Produces skydoc output in proto form. */
public class ProtoRenderer {

  private final ModuleInfo.Builder moduleInfo;

  public ProtoRenderer() {
    this.moduleInfo = ModuleInfo.newBuilder();
  }

  /** Appends {@link RuleInfo} protos to a {@link ModuleInfo.Builder}. */
  public ProtoRenderer appendRuleInfos(Collection<RuleInfo> ruleInfos) {
    for (RuleInfo ruleInfo : ruleInfos) {
      moduleInfo.addRuleInfo(ruleInfo);
    }
    return this;
  }

  /** Appends {@link ProviderInfo} protos to a {@link ModuleInfo.Builder}. */
  public ProtoRenderer appendProviderInfos(Collection<ProviderInfo> providerInfos) {
    for (ProviderInfo providerInfo : providerInfos) {
      moduleInfo.addProviderInfo(providerInfo);
    }
    return this;
  }

  /** Appends {@link StarlarkFunctionInfo} protos to a {@link ModuleInfo.Builder}. */
  public ProtoRenderer appendStarlarkFunctionInfos(Map<String, StarlarkFunction> funcInfosMap)
      throws DocstringParseException {
    for (Map.Entry<String, StarlarkFunction> entry : funcInfosMap.entrySet()) {
      StarlarkFunctionInfo funcInfo =
          FunctionUtil.fromNameAndFunction(entry.getKey(), entry.getValue());
      moduleInfo.addFuncInfo(funcInfo);
    }
    return this;
  }

  /** Appends module docstring protos to a {@link ModuleInfo.Builder}. */
  public ProtoRenderer setModuleDocstring(String moduleDoc) {
    moduleInfo.setModuleDocstring(moduleDoc);
    return this;
  }

  /** Outputs the raw form of a {@link ModuleInfo} proto. */
  public void writeModuleInfo(BufferedOutputStream outputStream) throws IOException {
    ModuleInfo build = moduleInfo.build();
    build.writeTo(outputStream);
  }

  /** Appends {@link AspectInfo} protos to a {@link ModuleInfo.Builder}. */
  public ProtoRenderer appendAspectInfos(Collection<AspectInfo> aspectInfos) {
    for (AspectInfo aspectInfo : aspectInfos) {
      moduleInfo.addAspectInfo(aspectInfo);
    }
    return this;
  }

  public ModuleInfo.Builder getModuleInfo() {
    return moduleInfo;
  }
}
