/*
 * Copyright 2012-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.android;

import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
import com.google.common.io.CharStreams;
import com.google.common.io.Files;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Scanner;
import java.util.SortedSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MergeAndroidResourcesStep implements Step {

  private static final Pattern TEXT_SYMBOLS_LINE = Pattern.compile("(\\S+) (\\S+) (\\S+) (.+)");

  private final ImmutableMap<String, String> symbolsFileToRDotJavaPackage;
  private final String pathToGeneratedJavaFiles;

  /**
   * Merges text symbols files from {@code aapt} into R.java files that can be compiled.
   * @param symbolsFileToRDotJavaPackage For each entry in the map, the key is a path to a symbols
   *     file generated by {@code aapt} using the {@code --output-text-symbols} flag. The value is
   *     the Java package for the corresponding R.java file.
   * @param pathToGeneratedJavaFiles the directory where the generated R.java files should be
   *     written. Admittedly, this command could write such files to a {@code /tmp} directory, but
   *     it is convenient to have the R.java files written to a known location for debugging. This
   *     directory should exist and be empty before this command is run.
   */
  public MergeAndroidResourcesStep(
      Map<String, String> symbolsFileToRDotJavaPackage,
      String pathToGeneratedJavaFiles) {
    this.symbolsFileToRDotJavaPackage = ImmutableMap.copyOf(symbolsFileToRDotJavaPackage);
    this.pathToGeneratedJavaFiles = Preconditions.checkNotNull(pathToGeneratedJavaFiles);
  }

  @Override
  public int execute(ExecutionContext context) {
    try {
      doExecute();
      return 0;
    } catch (IOException e) {
      e.printStackTrace(context.getStdErr());
      return 1;
    }
  }

  private void doExecute() throws IOException {
    // A symbols file may look like:
    //
    //    int id placeholder 0x7f020000
    //    int string debug_http_proxy_dialog_title 0x7f030004
    //    int string debug_http_proxy_hint 0x7f030005
    //    int string debug_http_proxy_summary 0x7f030003
    //    int string debug_http_proxy_title 0x7f030002
    //    int string debug_ssl_cert_check_summary 0x7f030001
    //    int string debug_ssl_cert_check_title 0x7f030000
    //
    // Note that there are four columns of information:
    // - the type of the resource id (always seems to be int or int[], in practice)
    // - the type of the resource
    // - the name of the resource
    // - the value of the resource id
    //
    // In order to convert this to R.java, all resources of the same type are grouped into a static
    // class of that name. The static class contains static values that correspond to the resource
    // (type, name, value) tuples.
    //
    // The first step is to merge symbol files of the same package type and resource type/name.
    // That is, within a package type, each resource type/name pair must be unique. If there are
    // multiple pairs, only one will be written to the R.java file.
    //
    // Because the resulting files do not match their respective resources.arsc, the values are
    // meaningless and do not represent the usable final result.  This is why the R.java file is
    // written without using final so that javac will not inline the values.  Unfortunately,
    // though Robolectric doesn't read resources.arsc, it does assert that all the R.java resource
    // ids are unique.  This forces us to re-enumerate new unique ids.
    SortedSetMultimap<String, Resource> rDotJavaPackageToResources = sortSymbols(
        new Function<String, Readable>() {
          @Override
          public Readable apply(String pathToFile) {
            try {
              return new FileReader(pathToFile);
            } catch (FileNotFoundException e) {
              throw new RuntimeException(e);
            }
          }
        },
        symbolsFileToRDotJavaPackage,
        true /* reenumerate */);

    // Create an R.java file for each package.
    for (String rDotJavaPackage : rDotJavaPackageToResources.keySet()) {
      // Create the content of R.java.
      SortedSet<Resource> resources = rDotJavaPackageToResources.get(rDotJavaPackage);

      // Write R.java in the pathToGeneratedJavaFiles directory. Admittedly, this will be written
      // to /tmp/com.example.stuff/R.java rather than /tmp/com/example/stuff/R.java. It turns out
      // that directory structure does not matter to javac.

      // Determine the path to R.java.
      File rDotJava = getOutputFile(pathToGeneratedJavaFiles, rDotJavaPackage);

      // Then write R.java to the output directory.
      Files.createParentDirs(rDotJava);
      BufferedWriter writer = Files.newWriter(rDotJava, Charsets.UTF_8);
      try {
        writeJavaCodeForPackageAndResources(new PrintWriter(writer),
            rDotJavaPackage, resources);
      } finally {
        writer.close();
      }
    }
  }

  @VisibleForTesting
  static SortedSetMultimap<String, Resource> sortSymbols(
      Function<String, Readable> filePathToReadable,
      Map<String, String> symbolsFileToRDotJavaPackage,
      boolean reenumerate) {
    // If we're reenumerating, start at 0x7f01001 so that the resulting file is human readable.
    // This value range (0x7f010001 - ...) is easier to spot as an actual resource id instead of
    // other values in styleable which can be enumerated integers starting at 0.
    IntEnumerator enumerator = reenumerate ? new IntEnumerator(0x7f01001) : null;
    SortedSetMultimap<String, Resource> rDotJavaPackageToSymbolsFiles = TreeMultimap.create();
    for (Map.Entry<String, String> entry : symbolsFileToRDotJavaPackage.entrySet()) {
      String symbolsFile = entry.getKey();
      String packageName = entry.getValue();

      // Read the symbols file and parse each line as a Resource.
      Readable readable = filePathToReadable.apply(symbolsFile);
      Scanner scanner = new Scanner(readable);
      while (scanner.hasNext()) {
        String line = scanner.nextLine();
        Matcher matcher = TEXT_SYMBOLS_LINE.matcher(line);
        boolean isMatch = matcher.matches();
        Preconditions.checkState(isMatch, "Should be able to match '%s'.", line);
        String idType = matcher.group(1);
        String type = matcher.group(2);
        String name = matcher.group(3);
        String idValue = matcher.group(4);

        // We're only doing the remapping so Roboelectric is happy and it is already ignoring the
        // id references found in the styleable section.  So let's do that as well so we don't have
        // to get fancier than is needed.  That is, just re-enumerate all app-level resource ids
        // and ignore everything else, allowing the styleable references to be messed up.
        String idValueToUse = idValue;
        if (reenumerate && idValue.startsWith("0x7f")) {
          idValueToUse = String.format("0x%08x", enumerator.next());
        }

        Resource resource = new Resource(idType, type, name, idValue, idValueToUse);
        rDotJavaPackageToSymbolsFiles.put(packageName, resource);
      }
    }
    return rDotJavaPackageToSymbolsFiles;
  }

  public static String generateJavaCodeForPackageWithoutResources(String packageName) {
    return generateJavaCodeForPackageAndResources(packageName, ImmutableSortedSet.<Resource>of());
  }

  public static String generateJavaCodeForPackageAndResources(String packageName,
      SortedSet<Resource> resources) {
    StringBuilder b = new StringBuilder();

    try (PrintWriter writer = new PrintWriter(CharStreams.asWriter(b))) {
      writeJavaCodeForPackageAndResources(writer, packageName, resources);
    } catch (IOException e) {
      // Impossible.
      throw new RuntimeException(e);
    }
    return b.toString();
  }

  /**
   * Writes an intermediate R.java with dummy values influenced by the also dummy values created by
   * {@code aapt} when building intermediate artifacts.
   *
   * @param writer Output writer for the Java source.
   * @param packageName Package of the resulting R.java file.
   * @param resources Sorted set of resources parsed from R.txt.  First sorted by type then name.
   */
  private static void writeJavaCodeForPackageAndResources(
      PrintWriter writer,
      String packageName,
      SortedSet<Resource> resources) throws IOException {
    Preconditions.checkNotNull(writer);
    Preconditions.checkNotNull(packageName);
    Preconditions.checkNotNull(resources);

    writer.append("package ").append(packageName).append(';').print('\n');
    writer.print('\n');
    writer.print("public class R {\n");
    writer.print('\n');

    String lastType = null;
    for (Resource res : resources) {
      String type = res.type;
      if (!type.equals(lastType)) {
        // If the previous type needs, to be closed, then close it.
        if (lastType != null) {
          writer.print("  }\n");
          writer.print('\n');
        }

        // Now start the block for the new type.
        writer.append("  public static class ").append(type).append(" {").print('\n');
        lastType = type;
      }

      // Write out the resource.
      // Write as an int.
      writer.print(String.format("    public static %s %s=%s;\n",
          res.idType,
          res.name,
          res.idValueToWrite));
    }

    // If some type was written (e.g., the for loop was entered), then the last type needs to be
    // closed.
    if (lastType != null) {
      writer.print("  }\n");
      writer.print('\n');
    }

    // Close the class definition.
    writer.print("}\n");
  }

  public static String getOutputFilePath(String pathToGeneratedJavaFiles, String rDotJavaPackage) {
    return getOutputFile(pathToGeneratedJavaFiles, rDotJavaPackage).getPath();
  }

  private static File getOutputFile(String pathToGeneratedJavaFiles, String rDotJavaPackage) {
    File outputDir = new File(pathToGeneratedJavaFiles, rDotJavaPackage);
    File rDotJava = new File(outputDir, "R.java");
    return rDotJava;
  }

  /** Represents a row from a symbols file generated by {@code aapt}. */
  @VisibleForTesting
  static class Resource implements Comparable<Resource> {
    @VisibleForTesting final String idType;
    @VisibleForTesting final String type;
    @VisibleForTesting final String name;
    @VisibleForTesting final String originalIdValue;
    @VisibleForTesting final String idValueToWrite;

    public Resource(String idType, String type, String name, String originalIdValue,
        String idValueToWrite) {
      this.idType = Preconditions.checkNotNull(idType);
      this.type = Preconditions.checkNotNull(type);
      this.name = Preconditions.checkNotNull(name);
      this.originalIdValue = Preconditions.checkNotNull(originalIdValue);
      this.idValueToWrite = Preconditions.checkNotNull(idValueToWrite);
    }

    /**
     * A collection of Resources should be sorted such that Resources of the same type should be
     * grouped together, and should be alphabetized within that group.
     */
    @Override
    public int compareTo(Resource that) {
      return ComparisonChain.start()
          .compare(this.type, that.type)
          .compare(this.name, that.name)
          .result();
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof Resource)) {
        return false;
      }

      Resource that = (Resource)obj;
      return Objects.equal(this.type, that.type) && Objects.equal(this.name, that.name);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(type, name);
    }

    @Override
    public String toString() {
      return Objects.toStringHelper(Resource.class)
          .add("idType", idType)
          .add("type", type)
          .add("name", name)
          .add("originalIdValue", originalIdValue)
          .add("idValueToWrite", idValueToWrite)
          .toString();
    }
  }

  @Override
  public String getShortName() {
    return "android-res-merge";
  }

  @Override
  public String getDescription(ExecutionContext context) {
    return getShortName() + " " + Joiner.on(' ').join(symbolsFileToRDotJavaPackage.keySet());
  }

  private static class IntEnumerator {
    private int value;

    public IntEnumerator(int start) {
      value = start;
    }

    public int next() {
      Preconditions.checkState(value < Integer.MAX_VALUE, "Stop goofing off");
      return value++;
    }
  }

}
