// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.android.tools.r8.dex;

import com.android.tools.r8.DataDirectoryResource;
import com.android.tools.r8.DataEntryResource;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppServices;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardPathFilter;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.io.ByteStreams;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntStack;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.function.Function;

public class ResourceAdapter {

  private final AppView<?> appView;
  private final DexItemFactory dexItemFactory;
  private final GraphLens graphLens;
  private final NamingLens namingLens;
  private final InternalOptions options;

  public ResourceAdapter(AppView<?> appView) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.graphLens = appView.graphLens();
    this.namingLens = appView.getNamingLens();
    this.options = appView.options();
  }

  public DataEntryResource adaptIfNeeded(DataEntryResource file) {
    // Adapt name, if needed.
    String name =
        shouldAdapt(file, options, ProguardConfiguration::getAdaptResourceFilenames)
            ? adaptFileName(file)
            : file.getName();
    assert name != null;
    // Adapt contents, if needed.
    byte[] contents =
        shouldAdapt(file, options, ProguardConfiguration::getAdaptResourceFileContents)
            ? adaptFileContents(file)
            : null;
    // Return a new resource if the name or contents changed. Otherwise return the original
    // resource as it was.
    if (contents != null) {
      // File contents was adapted. Return a new resource that has the new contents, and a new name,
      // if the filename was adapted.
      return DataEntryResource.fromBytes(contents, name, file.getOrigin());
    }
    if (!name.equals(file.getName())) {
      // File contents was not adapted, but filename was.
      return file.withName(name);
    }
    // Neither file contents nor filename was adapted.
    return file;
  }

  public DataDirectoryResource adaptIfNeeded(DataDirectoryResource directory) {
    // First check if this directory should even be in the output.
    if (options.getProguardConfiguration() == null) {
      assert options.testing.enableD8ResourcesPassThrough;
      return null;
    }
    if (!options.getProguardConfiguration().getKeepDirectories().matches(directory.getName())) {
      return null;
    }
    return DataDirectoryResource.fromName(adaptDirectoryName(directory), directory.getOrigin());
  }

  private boolean shouldAdapt(
      DataEntryResource file,
      InternalOptions options,
      Function<ProguardConfiguration, ProguardPathFilter> getFilter) {
    final ProguardConfiguration proguardConfiguration = options.getProguardConfiguration();
    if (proguardConfiguration == null) {
      assert options.testing.enableD8ResourcesPassThrough;
      return false;
    }
    ProguardPathFilter filter = getFilter.apply(proguardConfiguration);
    return filter.isEnabled()
        && !StringUtils.toLowerCase(file.getName()).endsWith(FileUtils.CLASS_EXTENSION)
        && filter.matches(file.getName());
  }

  public boolean isService(DataEntryResource file) {
    return file.getName().startsWith(AppServices.SERVICE_DIRECTORY_NAME);
  }

  private String adaptFileName(DataEntryResource file) {
    FileNameAdapter adapter =
        file.getName().startsWith(AppServices.SERVICE_DIRECTORY_NAME)
            ? new ServiceFileNameAdapter(file.getName())
            : new DefaultFileNameAdapter(file.getName());
    if (adapter.run()) {
      return adapter.getResult();
    }
    return file.getName();
  }

  private String adaptDirectoryName(DataDirectoryResource file) {
    DirectoryNameAdapter adapter = new DirectoryNameAdapter(file.getName());
    if (adapter.run()) {
      return adapter.getResult();
    }
    return file.getName();
  }

  // According to the Proguard documentation, the resource files should be parsed and written using
  // the platform's default character set.
  private byte[] adaptFileContents(DataEntryResource file) {
    try (InputStream in = file.getByteStream()) {
      byte[] bytes = ByteStreams.toByteArray(in);
      String contents = new String(bytes, Charset.defaultCharset());

      FileContentsAdapter adapter = new FileContentsAdapter(contents);
      if (adapter.run()) {
        return adapter.getResult().getBytes(Charset.defaultCharset());
      }
    } catch (ResourceException e) {
      options.reporter.error(
          new StringDiagnostic("Failed to open input: " + e.getMessage(), file.getOrigin()));
    } catch (Exception e) {
      options.reporter.error(new ExceptionDiagnostic(e, file.getOrigin()));
    }
    // Return null to signal that the file contents did not change. Otherwise we would have to copy
    // the original file for no reason.
    return null;
  }

  private abstract class StringAdapter {

    protected final String contents;
    private final StringBuilder result = new StringBuilder();

    // If any type names in `contents` have been updated. If this flag is still true in the end,
    // then we can simply use the resource as it was.
    private boolean changed = false;
    private int outputFrom = 0;
    private int position = 0;

    // When renaming Java type names, the adapter always looks for the longest name to rewrite.
    // For example, if there is a resource with the name "foo/bar/C$X$Y.txt", then the adapter will
    // check if there is a renaming for the type "foo.bar.C$X$Y". If there is no such renaming, then
    // -adaptresourcefilenames works in such a way that "foo/bar/C$X" should be rewritten if there
    // is a renaming for the type "foo.bar.C$X". Therefore, when scanning forwards to read the
    // substring "foo/bar/C$X$Y", this adapter records the positions of the two '$' characters in
    // the stack `prefixEndPositionsExclusive`, such that it can easily backtrack to the previously
    // valid, but shorter Java type name.
    //
    // Note that there is no backtracking for -adaptresourcefilecontents.
    private final IntStack prefixEndPositionsExclusive;

    public StringAdapter(String contents) {
      this.contents = contents;
      this.prefixEndPositionsExclusive = allowRenamingOfPrefixes() ? new IntArrayList() : null;
    }

    public boolean run() {
      do {
        handleMisc();
        handleJavaType();
      } while (!eof());
      if (changed) {
        // At least one type was renamed. We need to flush all characters in `contents` that follow
        // the last type that was renamed.
        outputRangeFromInput(outputFrom, contents.length());
      } else {
        // No types were renamed. In this case the adapter should simply have scanned through
        // `contents`, without outputting anything to `result`.
        assert outputFrom == 0;
        assert result.toString().isEmpty();
      }
      return changed;
    }

    public String getResult() {
      assert changed;
      return result.toString();
    }

    // Forwards the cursor until the current character is a Java identifier part.
    private void handleMisc() {
      while (!eof() && !Character.isJavaIdentifierPart(contents.charAt(position))) {
        position++;
      }
    }

    // Reads a Java type from the current position in `contents`, and then checks if the given
    // type has been renamed.
    private void handleJavaType() {
      if (eof()) {
        return;
      }

      assert !allowRenamingOfPrefixes() || prefixEndPositionsExclusive.isEmpty();

      assert Character.isJavaIdentifierPart(contents.charAt(position));
      int start = position++;
      while (!eof()) {
        char currentChar = contents.charAt(position);
        if (Character.isJavaIdentifierPart(currentChar)) {
          if (allowRenamingOfPrefixes()
              && shouldRecordPrefix(currentChar)
              && isRenamingCandidate(start, position)) {
            prefixEndPositionsExclusive.push(position);
          }
          position++;
          continue;
        }

        if (currentChar == getClassNameSeparator()
            && !eof(position + 1)
            && Character.isJavaIdentifierPart(contents.charAt(position + 1))) {
          if (allowRenamingOfPrefixes()
              && shouldRecordPrefix(currentChar)
              && isRenamingCandidate(start, position)) {
            prefixEndPositionsExclusive.push(position);
          }
          // Consume the separator and the Java identifier part that follows the separator.
          position += 2;
          continue;
        }

        // Not a valid extension of the type name.
        break;
      }

      if (allowRenamingOfPrefixes() && eof() && isRenamingCandidate(start, position)) {
        prefixEndPositionsExclusive.push(position);
      }

      boolean renamingSucceeded =
          isRenamingCandidate(start, position) && renameJavaTypeInRange(start, position);
      if (!renamingSucceeded && allowRenamingOfPrefixes()) {
        while (!prefixEndPositionsExclusive.isEmpty() && !renamingSucceeded) {
          int prefixEndExclusive = prefixEndPositionsExclusive.popInt();
          assert isRenamingCandidate(start, prefixEndExclusive);
          renamingSucceeded = handlePrefix(start, prefixEndExclusive);
        }
      }

      if (allowRenamingOfPrefixes()) {
        while (!prefixEndPositionsExclusive.isEmpty()) {
          prefixEndPositionsExclusive.popInt();
        }
      }
    }

    // Returns true if the Java type in the range [from; toExclusive[ was renamed.
    protected boolean renameJavaTypeInRange(int from, int toExclusive) {
      String javaType = contents.substring(from, toExclusive);
      if (getClassNameSeparator() != '.') {
        javaType = javaType.replace(getClassNameSeparator(), '.');
      }
      DexString descriptor =
          dexItemFactory.lookupString(
              DescriptorUtils.javaTypeToDescriptorIgnorePrimitives(javaType));
      DexType dexType = descriptor != null ? dexItemFactory.lookupType(descriptor) : null;
      if (dexType != null) {
        DexString renamedDescriptor = namingLens.lookupDescriptor(graphLens.lookupType(dexType));
        if (!descriptor.equals(renamedDescriptor)) {
          String renamedJavaType =
              DescriptorUtils.descriptorToJavaType(renamedDescriptor.toSourceString());
          // Need to flush all changes up to and excluding 'from', and then output the renamed
          // type.
          outputRangeFromInput(outputFrom, from);
          outputJavaType(
              getClassNameSeparator() != '.'
                  ? renamedJavaType.replace('.', getClassNameSeparator())
                  : renamedJavaType);
          outputFrom = toExclusive;
          changed = true;
          return true;
        }
      }
      return false;
    }

    // Returns true if the Java package in the range [from; toExclusive[ was renamed.
    protected boolean renameJavaPackageInRange(int from, int toExclusive) {
      String javaPackage = contents.substring(from, toExclusive);
      if (getClassNameSeparator() != '/') {
        javaPackage = javaPackage.replace(getClassNameSeparator(), '/');
      }
      String packageName = appView.graphLens().lookupPackageName(javaPackage);
      String minifiedJavaPackage = namingLens.lookupPackageName(packageName);
      if (!javaPackage.equals(minifiedJavaPackage)) {
        outputRangeFromInput(outputFrom, from);
        outputJavaType(
            getClassNameSeparator() != '/'
                ? minifiedJavaPackage.replace('/', getClassNameSeparator())
                : minifiedJavaPackage);
        outputFrom = toExclusive;
        changed = true;
        return true;
      }
      return false;
    }

    protected abstract char getClassNameSeparator();

    protected abstract boolean allowRenamingOfPrefixes();

    protected abstract boolean shouldRecordPrefix(char c);

    protected abstract boolean handlePrefix(int from, int toExclusive);

    protected abstract boolean isRenamingCandidate(int from, int toExclusive);

    private void outputRangeFromInput(int from, int toExclusive) {
      if (from < toExclusive) {
        result.append(contents, from, toExclusive);
      }
    }

    private void outputJavaType(String s) {
      result.append(s);
    }

    protected boolean eof() {
      return eof(position);
    }

    protected boolean eof(int position) {
      return position == contents.length();
    }
  }

  private class FileContentsAdapter extends StringAdapter {

    public FileContentsAdapter(String fileContents) {
      super(fileContents);
    }

    @Override
    public char getClassNameSeparator() {
      return '.';
    }

    @Override
    public boolean allowRenamingOfPrefixes() {
      return false;
    }

    @Override
    public boolean shouldRecordPrefix(char c) {
      throw new Unreachable();
    }

    @Override
    protected boolean handlePrefix(int from, int toExclusive) {
      throw new Unreachable();
    }

    @Override
    public boolean isRenamingCandidate(int from, int toExclusive) {
      // If the Java type starts with '-' or '.', it should not be renamed.
      return (from <= 0 || !isDashOrDot(contents.charAt(from - 1)))
          && (eof(toExclusive) || !isDashOrDot(contents.charAt(toExclusive)));
    }

    private boolean isDashOrDot(char c) {
      return c == '.' || c == '-';
    }
  }

  private abstract class FileNameAdapter extends StringAdapter {
    public FileNameAdapter(String filename) {
      super(filename);
    }

    @Override
    public char getClassNameSeparator() {
      return '/';
    }

    @Override
    public boolean allowRenamingOfPrefixes() {
      return true;
    }

    @Override
    public boolean shouldRecordPrefix(char c) {
      return !Character.isLetterOrDigit(c);
    }

    @Override
    protected boolean handlePrefix(int from, int toExclusive) {
      if (eof(toExclusive) || contents.charAt(toExclusive) == '/') {
        return renameJavaPackageInRange(from, toExclusive);
      }
      return renameJavaTypeInRange(from, toExclusive);
    }
  }

  private class DefaultFileNameAdapter extends FileNameAdapter {
    public DefaultFileNameAdapter(String filename) {
      super(filename);
    }

    @Override
    public boolean isRenamingCandidate(int from, int toExclusive) {
      return from == 0 && !eof(toExclusive);
    }
  }

  private class ServiceFileNameAdapter extends FileNameAdapter {
    public ServiceFileNameAdapter(String filename) {
      super(filename);
    }

    @Override
    public char getClassNameSeparator() {
      return '.';
    }

    @Override
    public boolean allowRenamingOfPrefixes() {
      return false;
    }

    @Override
    public boolean isRenamingCandidate(int from, int toExclusive) {
      return from == AppServices.SERVICE_DIRECTORY_NAME.length() && eof(toExclusive);
    }
  }

  private class DirectoryNameAdapter extends FileNameAdapter {
    public DirectoryNameAdapter(String filename) {
      super(filename);
    }

    @Override
    public boolean isRenamingCandidate(int from, int toExclusive) {
      return from == 0;
    }
  }
}
