/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.
 */

// Modifications are owned by the Chromium Authors.
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package build.android.gyp.resources_shrinker;

import static com.android.ide.common.symbols.SymbolIo.readFromAapt;
import static com.android.utils.SdkUtils.endsWithIgnoreCase;
import static com.google.common.base.Charsets.UTF_8;

import com.android.ide.common.resources.usage.ResourceUsageModel;
import com.android.ide.common.resources.usage.ResourceUsageModel.Resource;
import com.android.ide.common.symbols.Symbol;
import com.android.ide.common.symbols.SymbolTable;
import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.ResourceShrinker;
import com.android.tools.r8.ResourceShrinker.Command;
import com.android.tools.r8.ResourceShrinker.ReferenceChecker;
import com.android.tools.r8.origin.PathOrigin;
import com.android.utils.XmlUtils;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closeables;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import javax.xml.parsers.ParserConfigurationException;

/**
  Copied with modifications from gradle core source
  https://android.googlesource.com/platform/tools/base/+/master/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java

  Modifications are mostly to:
    - Remove unused code paths to reduce complexity.
    - Reduce dependencies unless absolutely required.
*/

public class Shrinker {
    private static final String ANDROID_RES = "android_res/";
    private static final String DOT_DEX = ".dex";
    private static final String DOT_CLASS = ".class";
    private static final String DOT_XML = ".xml";
    private static final String DOT_JAR = ".jar";
    private static final String FN_RESOURCE_TEXT = "R.txt";

    /* A source of resource classes to track, can be either a folder or a jar */
    private final Iterable<File> mRTxtFiles;
    private final File mProguardMapping;
    /** These can be class or dex files. */
    private final Iterable<File> mClasses;
    private final Iterable<File> mManifests;
    private final Iterable<File> mResourceDirs;

    private final File mReportFile;
    private final StringWriter mDebugOutput;
    private final PrintWriter mDebugPrinter;

    /** Easy way to invoke more verbose output for debugging */
    private boolean mDebug = false;

    /** The computed set of unused resources */
    private List<Resource> mUnused;

    /**
     * Map from resource class owners (VM format class) to corresponding resource entries.
     * This lets us map back from code references (obfuscated class and possibly obfuscated field
     * reference) back to the corresponding resource type and name.
     */
    private Map<String, Pair<ResourceType, Map<String, String>>> mResourceObfuscation =
            Maps.newHashMapWithExpectedSize(30);

    /** Obfuscated name of android/support/v7/widget/SuggestionsAdapter.java */
    private String mSuggestionsAdapter;

    /** Obfuscated name of android/support/v7/internal/widget/ResourcesWrapper.java */
    private String mResourcesWrapper;

    /* A Pair class because java does not come with batteries included. */
    private static class Pair<U, V> {
        private U mFirst;
        private V mSecond;

        Pair(U first, V second) {
            this.mFirst = first;
            this.mSecond = second;
        }

        public U getFirst() {
            return mFirst;
        }

        public V getSecond() {
            return mSecond;
        }
    }

    public Shrinker(Iterable<File> rTxtFiles, Iterable<File> classes, Iterable<File> manifests,
            File mapping, Iterable<File> resources, File reportFile) {
        mRTxtFiles = rTxtFiles;
        mProguardMapping = mapping;
        mClasses = classes;
        mManifests = manifests;
        mResourceDirs = resources;

        mReportFile = reportFile;
        if (reportFile != null) {
            mDebugOutput = new StringWriter(8 * 1024);
            mDebugPrinter = new PrintWriter(mDebugOutput);
        } else {
            mDebugOutput = null;
            mDebugPrinter = null;
        }
    }

    public void close() {
        if (mDebugOutput != null) {
            String output = mDebugOutput.toString();

            if (mReportFile != null) {
                File dir = mReportFile.getParentFile();
                if (dir != null) {
                    if ((dir.exists() || dir.mkdir()) && dir.canWrite()) {
                        try {
                            Files.asCharSink(mReportFile, Charsets.UTF_8).write(output);
                        } catch (IOException ignore) {
                        }
                    }
                }
            }
        }
    }

    public void analyze() throws IOException, ParserConfigurationException, SAXException {
        gatherResourceValues(mRTxtFiles);
        recordMapping(mProguardMapping);

        for (File jarOrDir : mClasses) {
            recordClassUsages(jarOrDir);
        }
        recordManifestUsages(mManifests);
        recordResources(mResourceDirs);
        dumpReferences();
        mModel.processToolsAttributes();
        mUnused = mModel.findUnused();
    }

    public void emitConfig(Path destination) throws IOException {
        File destinationFile = destination.toFile();
        if (!destinationFile.exists()) {
            destinationFile.getParentFile().mkdirs();
            boolean success = destinationFile.createNewFile();
            if (!success) {
                throw new IOException("Could not create " + destination);
            }
        }
        StringBuilder sb = new StringBuilder();
        Collections.sort(mUnused);
        for (Resource resource : mUnused) {
            sb.append(resource.type + "/" + resource.name + "#remove\n");
        }
        Files.asCharSink(destinationFile, UTF_8).write(sb.toString());
    }

    private void dumpReferences() {
        if (mDebugPrinter != null) {
            mDebugPrinter.print(mModel.dumpReferences());
        }
    }

    private void recordResources(Iterable<File> resources)
            throws IOException, SAXException, ParserConfigurationException {
        for (File resDir : resources) {
            File[] resourceFolders = resDir.listFiles();
            if (resourceFolders != null) {
                for (File folder : resourceFolders) {
                    ResourceFolderType folderType =
                            ResourceFolderType.getFolderType(folder.getName());
                    if (folderType != null) {
                        recordResources(folderType, folder);
                    }
                }
            }
        }
    }

    private void recordResources(ResourceFolderType folderType, File folder)
            throws ParserConfigurationException, SAXException, IOException {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                String path = file.getPath();
                mModel.file = file;
                try {
                    boolean isXml = endsWithIgnoreCase(path, DOT_XML);
                    if (isXml) {
                        String xml = Files.toString(file, UTF_8);
                        Document document = XmlUtils.parseDocument(xml, true);
                        mModel.visitXmlDocument(file, folderType, document);
                    } else {
                        mModel.visitBinaryResource(folderType, file);
                    }
                } finally {
                    mModel.file = null;
                }
            }
        }
    }

    void recordMapping(File mapping) throws IOException {
        if (mapping == null || !mapping.exists()) {
            return;
        }
        final String arrowString = " -> ";
        final String resourceString = ".R$";
        Map<String, String> nameMap = null;
        for (String line : Files.readLines(mapping, UTF_8)) {
            if (line.startsWith(" ") || line.startsWith("\t")) {
                if (nameMap != null) {
                    // We're processing the members of a resource class: record names into the map
                    int n = line.length();
                    int i = 0;
                    for (; i < n; i++) {
                        if (!Character.isWhitespace(line.charAt(i))) {
                            break;
                        }
                    }
                    if (i < n && line.startsWith("int", i)) { // int or int[]
                        int start = line.indexOf(' ', i + 3) + 1;
                        int arrow = line.indexOf(arrowString);
                        if (start > 0 && arrow != -1) {
                            int end = line.indexOf(' ', start + 1);
                            if (end != -1) {
                                String oldName = line.substring(start, end);
                                String newName =
                                        line.substring(arrow + arrowString.length()).trim();
                                if (!newName.equals(oldName)) {
                                    nameMap.put(newName, oldName);
                                }
                            }
                        }
                    }
                }
                continue;
            } else {
                nameMap = null;
            }
            int index = line.indexOf(resourceString);
            if (index == -1) {
                // Record obfuscated names of a few known appcompat usages of
                // Resources#getIdentifier that are unlikely to be used for general
                // resource name reflection
                if (line.startsWith("android.support.v7.widget.SuggestionsAdapter ")) {
                    mSuggestionsAdapter =
                            line.substring(line.indexOf(arrowString) + arrowString.length(),
                                        line.indexOf(':') != -1 ? line.indexOf(':') : line.length())
                                    .trim()
                                    .replace('.', '/')
                            + DOT_CLASS;
                } else if (line.startsWith("android.support.v7.internal.widget.ResourcesWrapper ")
                        || line.startsWith("android.support.v7.widget.ResourcesWrapper ")
                        || (mResourcesWrapper == null // Recently wrapper moved
                                && line.startsWith(
                                        "android.support.v7.widget.TintContextWrapper$TintResources "))) {
                    mResourcesWrapper =
                            line.substring(line.indexOf(arrowString) + arrowString.length(),
                                        line.indexOf(':') != -1 ? line.indexOf(':') : line.length())
                                    .trim()
                                    .replace('.', '/')
                            + DOT_CLASS;
                }
                continue;
            }
            int arrow = line.indexOf(arrowString, index + 3);
            if (arrow == -1) {
                continue;
            }
            String typeName = line.substring(index + resourceString.length(), arrow);
            ResourceType type = ResourceType.fromClassName(typeName);
            if (type == null) {
                continue;
            }
            int end = line.indexOf(':', arrow + arrowString.length());
            if (end == -1) {
                end = line.length();
            }
            String target = line.substring(arrow + arrowString.length(), end).trim();
            String ownerName = target.replace('.', '/');

            nameMap = Maps.newHashMap();
            Pair<ResourceType, Map<String, String>> pair = new Pair(type, nameMap);
            mResourceObfuscation.put(ownerName, pair);
            // For fast lookup in isResourceClass
            mResourceObfuscation.put(ownerName + DOT_CLASS, pair);
        }
    }

    private void recordManifestUsages(File manifest)
            throws IOException, ParserConfigurationException, SAXException {
        String xml = Files.toString(manifest, UTF_8);
        Document document = XmlUtils.parseDocument(xml, true);
        mModel.visitXmlDocument(manifest, null, document);
    }

    private void recordManifestUsages(Iterable<File> manifests)
            throws IOException, ParserConfigurationException, SAXException {
        for (File manifest : manifests) {
            recordManifestUsages(manifest);
        }
    }

    private void recordClassUsages(File file) throws IOException {
        assert file.isFile();
        if (file.getPath().endsWith(DOT_DEX)) {
            byte[] bytes = Files.toByteArray(file);
            recordClassUsages(file, file.getName(), bytes);
        } else if (file.getPath().endsWith(DOT_JAR)) {
            ZipInputStream zis = null;
            try {
                FileInputStream fis = new FileInputStream(file);
                try {
                    zis = new ZipInputStream(fis);
                    ZipEntry entry = zis.getNextEntry();
                    while (entry != null) {
                        String name = entry.getName();
                        if (name.endsWith(DOT_DEX)) {
                            byte[] bytes = ByteStreams.toByteArray(zis);
                            if (bytes != null) {
                                recordClassUsages(file, name, bytes);
                            }
                        }

                        entry = zis.getNextEntry();
                    }
                } finally {
                    Closeables.close(fis, true);
                }
            } finally {
                Closeables.close(zis, true);
            }
        }
    }

    private void recordClassUsages(File file, String name, byte[] bytes) {
        assert name.endsWith(DOT_DEX);
        ReferenceChecker callback = new ReferenceChecker() {
            @Override
            public boolean shouldProcess(String internalName) {
                return !isResourceClass(internalName + DOT_CLASS);
            }

            @Override
            public void referencedInt(int value) {
                Shrinker.this.referencedInt("dex", value, file, name);
            }

            @Override
            public void referencedString(String value) {
                // do nothing.
            }

            @Override
            public void referencedStaticField(String internalName, String fieldName) {
                Resource resource = getResourceFromCode(internalName, fieldName);
                if (resource != null) {
                    ResourceUsageModel.markReachable(resource);
                }
            }

            @Override
            public void referencedMethod(
                    String internalName, String methodName, String methodDescriptor) {
                // Do nothing.
            }
        };
        ProgramResource resource = ProgramResource.fromBytes(
                new PathOrigin(file.toPath()), ProgramResource.Kind.DEX, bytes, null);
        ProgramResourceProvider provider = () -> Arrays.asList(resource);
        try {
            Command command =
                    (new ResourceShrinker.Builder()).addProgramResourceProvider(provider).build();
            ResourceShrinker.run(command, callback);
        } catch (CompilationFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /** Returns whether the given class file name points to an aapt-generated compiled R class. */
    boolean isResourceClass(String name) {
        if (mResourceObfuscation.containsKey(name)) {
            return true;
        }
        int index = name.lastIndexOf('/');
        if (index != -1 && name.startsWith("R$", index + 1) && name.endsWith(DOT_CLASS)) {
            String typeName = name.substring(index + 3, name.length() - DOT_CLASS.length());
            return ResourceType.fromClassName(typeName) != null;
        }
        return false;
    }

    Resource getResourceFromCode(String owner, String name) {
        Pair<ResourceType, Map<String, String>> pair = mResourceObfuscation.get(owner);
        if (pair != null) {
            ResourceType type = pair.getFirst();
            Map<String, String> nameMap = pair.getSecond();
            String renamedField = nameMap.get(name);
            if (renamedField != null) {
                name = renamedField;
            }
            return mModel.getResource(type, name);
        }
        if (isValidResourceType(owner)) {
            ResourceType type =
                    ResourceType.fromClassName(owner.substring(owner.lastIndexOf('$') + 1));
            if (type != null) {
                return mModel.getResource(type, name);
            }
        }
        return null;
    }

    private Boolean isValidResourceType(String candidateString) {
        return candidateString.contains("/")
                && candidateString.substring(candidateString.lastIndexOf('/') + 1).contains("$");
    }

    private void gatherResourceValues(Iterable<File> rTxts) throws IOException {
        for (File rTxt : rTxts) {
            assert rTxt.isFile();
            assert rTxt.getName().endsWith(FN_RESOURCE_TEXT);
            addResourcesFromRTxtFile(rTxt);
        }
    }

    private void addResourcesFromRTxtFile(File file) {
        try {
            SymbolTable st = readFromAapt(file, null);
            for (Symbol symbol : st.getSymbols().values()) {
                String symbolValue = symbol.getValue();
                if (symbol.getResourceType() == ResourceType.STYLEABLE) {
                    if (symbolValue.trim().startsWith("{")) {
                        // Only add the styleable parent, styleable children are not yet supported.
                        mModel.addResource(symbol.getResourceType(), symbol.getName(), null);
                    }
                } else {
                    mModel.addResource(symbol.getResourceType(), symbol.getName(), symbolValue);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    ResourceUsageModel getModel() {
        return mModel;
    }

    private void referencedInt(String context, int value, File file, String currentClass) {
        Resource resource = mModel.getResource(value);
        if (ResourceUsageModel.markReachable(resource) && mDebug) {
            assert mDebugPrinter != null : "mDebug is true, but mDebugPrinter is null.";
            mDebugPrinter.println("Marking " + resource + " reachable: referenced from " + context
                    + " in " + file + ":" + currentClass);
        }
    }

    private final ResourceShrinkerUsageModel mModel = new ResourceShrinkerUsageModel();

    private class ResourceShrinkerUsageModel extends ResourceUsageModel {
        public File file;

        /**
         * Whether we should ignore tools attribute resource references.
         * <p>
         * For example, for resource shrinking we want to ignore tools attributes,
         * whereas for resource refactoring on the source code we do not.
         *
         * @return whether tools attributes should be ignored
         */
        @Override
        protected boolean ignoreToolsAttributes() {
            return true;
        }

        @Override
        protected void onRootResourcesFound(List<Resource> roots) {
            if (mDebugPrinter != null) {
                mDebugPrinter.println(
                        "\nThe root reachable resources are:\n" + Joiner.on(",\n   ").join(roots));
            }
        }

        @Override
        protected Resource declareResource(ResourceType type, String name, Node node) {
            Resource resource = super.declareResource(type, name, node);
            resource.addLocation(file);
            return resource;
        }

        @Override
        protected void referencedString(String string) {
            // Do nothing
        }
    }

    public static void main(String[] args) throws Exception {
        List<File> rTxtFiles = null; // R.txt files
        List<File> classes = null; // Dex/jar w dex
        List<File> manifests = null; // manifests
        File mapping = null; // mapping
        List<File> resources = null; // resources dirs
        File log = null; // output log for debugging
        Path configPath = null; // output config
        for (int i = 0; i < args.length; i += 2) {
            switch (args[i]) {
                case "--rtxts":
                    rTxtFiles = Arrays.stream(args[i + 1].split(":"))
                                        .map(s -> new File(s))
                                        .collect(Collectors.toList());
                    break;
                case "--dex":
                    classes = Arrays.stream(args[i + 1].split(":"))
                                      .map(s -> new File(s))
                                      .collect(Collectors.toList());
                    break;
                case "--manifests":
                    manifests = Arrays.stream(args[i + 1].split(":"))
                                        .map(s -> new File(s))
                                        .collect(Collectors.toList());
                    break;
                case "--mapping":
                    mapping = new File(args[i + 1]);
                    break;
                case "--resourceDirs":
                    resources = Arrays.stream(args[i + 1].split(":"))
                                        .map(s -> new File(s))
                                        .collect(Collectors.toList());
                    break;
                case "--log":
                    log = new File(args[i + 1]);
                    break;
                case "--outputConfig":
                    configPath = Paths.get(args[i + 1]);
                    break;
                default:
                    throw new IllegalArgumentException(args[i] + " is not a valid arg.");
            }
        }
        Shrinker shrinker = new Shrinker(rTxtFiles, classes, manifests, mapping, resources, log);
        shrinker.analyze();
        shrinker.close();
        shrinker.emitConfig(configPath);
    }
}
