// 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.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.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,
      DexItemFactory dexItemFactory,
      GraphLens graphLens,
      NamingLens namingLens,
      InternalOptions options) {
    this.appView = appView;
    this.dexItemFactory = dexItemFactory;
    this.graphLens = graphLens;
    this.namingLens = namingLens;
    this.options = 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()
        && !file.getName().toLowerCase().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;
    }
  }
}
