/*
 * Copyright 2013-present Facebook, Inc.
 *
 * 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.facebook.buck.ocaml;

import com.facebook.buck.cxx.CxxPreprocessorInput;
import com.facebook.buck.cxx.CxxSource;
import com.facebook.buck.cxx.NativeLinkableInput;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.UnflavoredBuildTarget;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.util.MoreIterables;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

import java.nio.file.Path;
import java.nio.file.Paths;

import javax.annotation.Nullable;


public class OCamlBuildContext {
  static final String OCAML_COMPILED_BYTECODE_DIR = "bc";
  static final String OCAML_COMPILED_DIR = "opt";
  private static final String OCAML_GENERATED_SOURCE_DIR = "gen";

  static final Path DEFAULT_OCAML_BYTECODE_COMPILER =
      Paths.get("/usr/bin/ocamlc.opt");
  static final Path DEFAULT_OCAML_YACC_COMPILER = Paths.get("/usr/bin/ocamlyacc");
  static final Path DEFAULT_OCAML_LEX_COMPILER = Paths.get("/usr/bin/ocamllex.opt");
  static final Path DEFAULT_OCAML_COMPILER = Paths.get("/usr/bin/ocamlopt.opt");
  static final Path DEFAULT_OCAML_DEP_TOOL = Paths.get("/usr/bin/ocamldep.opt");
  static final Path DEFAULT_OCAML_DEBUG = Paths.get("/usr/bin/ocamldebug");
  static final Path DEFAULT_OCAML_INTEROP_INCLUDE_DIR = Paths.get("/usr/local/lib/ocaml");

  @Nullable
  private OCamlBuckConfig config;
  @Nullable
  private Path ocamlDepTool;
  @Nullable
  private Path ocamlCompiler;
  @Nullable
  private Path ocamlBytecodeCompiler;
  @Nullable
  private Path ocamlDebug;
  private boolean isLibrary;
  @Nullable
  private ImmutableList<String> flags;
  @Nullable
  private Path output;
  @Nullable
  private Path bytecodeOutput;
  @Nullable
  private ImmutableList<Path> input;
  @Nullable
  private ImmutableList<String> includes;
  @Nullable
  private NativeLinkableInput linkableInput;
  @Nullable
  private ImmutableList<OCamlLibrary> ocamlInput;
  @Nullable
  private Path yaccCompiler;
  @Nullable
  private Path lexCompiler;
  @Nullable
  private Path compileOutputDir;
  @Nullable
  private Path compileBytecodeOutputDir;
  @Nullable
  private Path generatedSourceDir;
  @Nullable
  private CxxPreprocessorInput cxxPreprocessorInput;
  @Nullable
  private ImmutableSet<Path> cInput;
  @Nullable
  private ImmutableSet<Path> lexInput;
  @Nullable
  private ImmutableSet<Path> yaccInputs;
  @Nullable
  private ImmutableSet<Path> mlInput;
  @Nullable
  private ImmutableList<String> bytecodeIncludes;

  private static Path getArchiveOutputPath(UnflavoredBuildTarget target) {
    return BuildTargets.getGenPath(
        target,
        "%s/lib" + target.getShortName() + OCamlCompilables.OCAML_CMXA);
  }

  private static Path getArchiveBytecodeOutputPath(UnflavoredBuildTarget target) {
    return BuildTargets.getGenPath(
        target,
        "%s/lib" + target.getShortName() + OCamlCompilables.OCAML_CMA);
  }

  public static Path getOutputPath(BuildTarget target, boolean isLibrary) {
    UnflavoredBuildTarget plainTarget = target.getUnflavoredBuildTarget();
    if (isLibrary) {
      return getArchiveOutputPath(plainTarget);
    } else {
      return BuildTargets.getBinPath(
          plainTarget,
          "%s/" + plainTarget.getShortName() + ".opt");
    }
  }

  public static Path getBytecodeOutputPath(BuildTarget target, boolean isLibrary) {
    UnflavoredBuildTarget plainTarget = target.getUnflavoredBuildTarget();
    if (isLibrary) {
      return getArchiveBytecodeOutputPath(plainTarget);
    } else {
      return BuildTargets.getBinPath(
          plainTarget,
          "%s/" + plainTarget.getShortName());
    }
  }

  private static Path getGeneratedSourceDir(BuildTarget buildTarget, boolean isLibrary) {
    return getOutputPath(buildTarget, isLibrary).getParent().resolve(
        OCAML_GENERATED_SOURCE_DIR);
  }

  public static Path getCompileOutputDir(BuildTarget buildTarget, boolean isLibrary) {
    return getOutputPath(buildTarget, isLibrary).getParent().resolve(
        OCAML_COMPILED_DIR);
  }

  public static Path getCompileBytecodeOutputDir(BuildTarget buildTarget, boolean isLibrary) {
    return getOutputPath(buildTarget, isLibrary).getParent().resolve(
        OCAML_COMPILED_BYTECODE_DIR);
  }

  public Path getCOutput(Path cSrc) {
    String inputFileName = cSrc.getFileName().toString();
    String outputFileName = inputFileName
        .replaceFirst(
            OCamlCompilables.OCAML_C_REGEX,
            OCamlCompilables.OCAML_O);
    return getCompileOutputDir().resolve(outputFileName);
  }

  public Function<Path, Path> toCOutput() {
    return new Function<Path, Path>() {
      @Override
      public Path apply(Path input) {
        return getCOutput(input);
      }
    };
  }

  public static Builder builder(OCamlBuckConfig config, SourcePathResolver resolver) {
    return new Builder(new OCamlBuildContext(), config, resolver);
  }

  public Path getOcamlDepTool() {
    return Preconditions.checkNotNull(ocamlDepTool);
  }

  public Path getOcamlCompiler() {
    return Preconditions.checkNotNull(ocamlCompiler);
  }

  public Path getOcamlDebug() {
    return Preconditions.checkNotNull(ocamlDebug);
  }

  public boolean isLibrary() {
    return isLibrary;
  }

  public ImmutableList<String> getFlags() {
    return Preconditions.checkNotNull(flags);
  }

  public Path getOutput() {
    return Preconditions.checkNotNull(output);
  }

  public Path getBytecodeOutput() {
    return Preconditions.checkNotNull(bytecodeOutput);
  }

  public ImmutableList<Path> getInput() {
    return Preconditions.checkNotNull(input);
  }

  public ImmutableList<String> getIncludes() {
    return Preconditions.checkNotNull(includes);
  }

  public NativeLinkableInput getLinkableInput() {
    return Preconditions.checkNotNull(linkableInput);
  }

  public ImmutableList<OCamlLibrary> getOCamlInput() {
    return Preconditions.checkNotNull(ocamlInput);
  }

  public Path getYaccCompiler() {
    return Preconditions.checkNotNull(yaccCompiler);
  }

  public Path getLexCompiler() {
    return Preconditions.checkNotNull(lexCompiler);
  }

  public Path getCompileOutputDir() {
    return Preconditions.checkNotNull(compileOutputDir);
  }

  public Path getGeneratedSourceDir() {
    return Preconditions.checkNotNull(generatedSourceDir);
  }

  public CxxPreprocessorInput getCxxPreprocessorInput() {
    return Preconditions.checkNotNull(cxxPreprocessorInput);
  }

  public Path getCompileBytecodeOutputDir() {
    return Preconditions.checkNotNull(compileBytecodeOutputDir);
  }

  public Path getOcamlBytecodeCompiler() {
    return Preconditions.checkNotNull(ocamlBytecodeCompiler);
  }

  public ImmutableList<String> getIncludeDirectories(boolean isBytecode, boolean excludeDeps) {
    Preconditions.checkNotNull(mlInput);

    ImmutableSet.Builder<String> includeDirs = ImmutableSet.builder();
    for (Path mlFile : mlInput) {
      Path parent = mlFile.getParent();
      if (parent != null) {
        includeDirs.add(parent.toString());
      }
    }

    if (!excludeDeps) {
      includeDirs.addAll(isBytecode ? this.getBytecodeIncludes() : this.getIncludes());
    }

    return ImmutableList.copyOf(includeDirs.build());
  }

  public ImmutableList<String> getIncludeFlags(boolean isBytecode, boolean excludeDeps) {
    Preconditions.checkNotNull(mlInput);
    return ImmutableList.copyOf(
        MoreIterables.zipAndConcat(
            Iterables.cycle(OCamlCompilables.OCAML_INCLUDE_FLAG),
            getIncludeDirectories(isBytecode, excludeDeps)));
  }

  public ImmutableList<String> getBytecodeIncludeFlags() {
    return ImmutableList.copyOf(
        MoreIterables.zipAndConcat(
            Iterables.cycle(OCamlCompilables.OCAML_INCLUDE_FLAG),
            getBytecodeIncludeDirectories()));
  }

  public ImmutableList<String> getBytecodeIncludeDirectories() {
    ImmutableList.Builder<String> includesBuilder = ImmutableList.builder();
    includesBuilder.addAll(getIncludeDirectories(true, /* excludeDeps */ true));
    includesBuilder.add(getCompileBytecodeOutputDir().toString());
    return includesBuilder.build();
  }

  protected FluentIterable<Path> getLexOutput(ImmutableSet<Path> lexInputs) {
    return FluentIterable.from(lexInputs)
        .transform(
            new Function<Path, Path>() {
              @Override
              public Path apply(Path lexInput) {
                return getGeneratedSourceDir().resolve(
                    lexInput.getFileName().toString().replaceFirst(
                        OCamlCompilables.OCAML_MLL_REGEX,
                        OCamlCompilables.OCAML_ML));
              }
            });
  }

  protected FluentIterable<Path> getYaccOutput(ImmutableSet<Path> yaccInputs) {
    return FluentIterable.from(yaccInputs)
        .transformAndConcat(
            new Function<Path, Iterable<? extends Path>>() {
              @Override
              public Iterable<? extends Path> apply(Path yaccInput) {
                String yaccFileName = yaccInput.getFileName().toString();
                return ImmutableList.of(
                    getGeneratedSourceDir().resolve(
                        yaccFileName.replaceFirst(
                            OCamlCompilables.OCAML_MLY_REGEX,
                            OCamlCompilables.OCAML_ML)),
                    getGeneratedSourceDir().resolve(
                        yaccFileName.replaceFirst(
                            OCamlCompilables.OCAML_MLY_REGEX,
                            OCamlCompilables.OCAML_MLI)));
              }
            });
  }

  public ImmutableList<Path> getCInput() {
    return Preconditions.checkNotNull(cInput).asList();
  }

  public ImmutableList<Path> getLexInput() {
    return Preconditions.checkNotNull(lexInput).asList();
  }

  public ImmutableList<Path> getYaccInput() {
    return Preconditions.checkNotNull(yaccInputs).asList();
  }

  public ImmutableList<Path> getMLInput() {
    return Preconditions.checkNotNull(mlInput).asList();
  }

  public RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) {
    return builder
        .setReflectively("ocamlDepTool", getOcamlDepTool())
        .setReflectively("ocamlCompiler", getOcamlCompiler())
        .setReflectively("ocamlBytecodeCompiler", getOcamlBytecodeCompiler())
        .setReflectively("ocamlDebug", getOcamlDebug())
        .setReflectively("yaccCompiler", getYaccCompiler())
        .setReflectively("lexCompiler", getLexCompiler())
        .setReflectively("flags", getFlags());
  }

  public ImmutableList<String> getBytecodeIncludes() {
    return Preconditions.checkNotNull(bytecodeIncludes);
  }

  public ImmutableList<String> getCCompileFlags() {
    ImmutableList.Builder<String> compileFlags = ImmutableList.builder();

    CxxPreprocessorInput cxxPreprocessorInput = getCxxPreprocessorInput();

    for (Path includes : cxxPreprocessorInput.getIncludeRoots()) {
      compileFlags.add("-ccopt", "-I" + includes.toString());
    }

    for (Path includes : cxxPreprocessorInput.getSystemIncludeRoots()) {
      compileFlags.add("-ccopt", "-isystem" + includes.toString());
    }

    for (String cFlag : cxxPreprocessorInput.getPreprocessorFlags().get(CxxSource.Type.C)) {
      compileFlags.add("-ccopt", cFlag);
    }

    return compileFlags.build();
  }

  private static ImmutableList<String> addPrefix(String prefix, Iterable<String> flags) {
    return ImmutableList.copyOf(
      MoreIterables.zipAndConcat(
        Iterables.cycle(prefix),
        flags));
  }

  public ImmutableList<String> getCommonCFlags() {
    ImmutableList.Builder<String> builder = ImmutableList.builder();
    builder.addAll(addPrefix("-ccopt", Preconditions.checkNotNull(config).getCFlags()));
    builder.add("-ccopt",
        "-isystem" +
            config.getOCamlInteropIncludesDir()
                .or(DEFAULT_OCAML_INTEROP_INCLUDE_DIR.toString()));
    return builder.build();
  }

  public ImmutableList<String> getCommonCLinkerFlags() {
    Preconditions.checkNotNull(config);
    return addPrefix("-ccopt",
        Iterables.concat(
          config.getCLinkerFlags(),
          addPrefix("-Xlinker", config.getLdFlags())));
  }


  public static class Builder {
    private final OCamlBuildContext context;
    private final SourcePathResolver resolver;

    private Builder(
        OCamlBuildContext context,
        OCamlBuckConfig config,
        SourcePathResolver resolver) {
      this.context = context;
      this.resolver = resolver;
      context.config = config;
      context.ocamlDepTool = config.getOCamlDepTool().or(DEFAULT_OCAML_DEP_TOOL);
      context.ocamlCompiler = config.getOCamlCompiler().or(DEFAULT_OCAML_COMPILER);
      context.ocamlBytecodeCompiler = config.getOCamlBytecodeCompiler()
          .or(DEFAULT_OCAML_BYTECODE_COMPILER);
      context.ocamlDebug = config.getOCamlDebug().or(DEFAULT_OCAML_DEBUG);
      context.yaccCompiler = config.getYaccCompiler()
          .or(DEFAULT_OCAML_YACC_COMPILER);
      context.lexCompiler = config.getLexCompiler().or(DEFAULT_OCAML_LEX_COMPILER);
    }

    Builder setFlags(ImmutableList<String> flags) {
      context.flags = flags;
      return this;
    }

    Builder setInput(ImmutableList<SourcePath> input) {
      Preconditions.checkNotNull(
          context.getGeneratedSourceDir(),
          "You should initialize directories before the call to setInput");

      FluentIterable<Path> inputPaths = FluentIterable.from(input)
          .transform(resolver.getPathFunction());

      context.input = inputPaths.toList();
      context.cInput = inputPaths.filter(OCamlUtil.ext(OCamlCompilables.OCAML_C)).toSet();
      context.lexInput = inputPaths.filter(OCamlUtil.ext(OCamlCompilables.OCAML_MLL)).toSet();
      context.yaccInputs = inputPaths.filter(OCamlUtil.ext(OCamlCompilables.OCAML_MLY)).toSet();
      context.mlInput = ImmutableSet.copyOf(
          Iterables.concat(
            inputPaths.filter(
                    OCamlUtil.ext(
                        OCamlCompilables.OCAML_ML,
                        OCamlCompilables.OCAML_MLI)),
            context.getLexOutput(Preconditions.checkNotNull(context.lexInput)),
            context.getYaccOutput(Preconditions.checkNotNull(context.yaccInputs))));
      return this;
    }

    Builder setIncludes(ImmutableList<String> includes) {
      context.includes = includes;
      return this;
    }

    Builder setLinkableInput(NativeLinkableInput linkableInput) {
      context.linkableInput = linkableInput;
      return this;
    }

    public Builder setOcamlInput(ImmutableList<OCamlLibrary> ocamlInput) {
      context.ocamlInput = ocamlInput;
      return this;
    }

    Builder setUpDirectories(BuildTarget buildTarget, boolean isLibrary) {
      context.isLibrary = isLibrary;
      context.output = getOutputPath(buildTarget, isLibrary);
      context.bytecodeOutput = getBytecodeOutputPath(buildTarget, isLibrary);
      context.compileOutputDir = getCompileOutputDir(buildTarget, isLibrary);
      context.compileBytecodeOutputDir = getCompileBytecodeOutputDir(buildTarget, isLibrary);
      context.generatedSourceDir = getGeneratedSourceDir(buildTarget, isLibrary);
      return this;
    }

    public Builder setCxxPreprocessorInput(CxxPreprocessorInput cxxPreprocessorInputFromDeps) {
      context.cxxPreprocessorInput = cxxPreprocessorInputFromDeps;
      return this;
    }

    OCamlBuildContext build() {
      return context;
    }

    public Builder setBytecodeIncludes(ImmutableList<String> bytecodeIncludes) {
      context.bytecodeIncludes = bytecodeIncludes;
      return this;
    }
  }

}
