/*
 * Copyright (C) 2022 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.
 */

package com.android.build.shrinker;

import static com.android.ide.common.resources.ResourcesUtil.resourceNameToFieldName;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.lang.Character.isDigit;

import com.android.annotations.NonNull;
import com.android.ide.common.resources.usage.ResourceStore;
import com.android.ide.common.resources.usage.ResourceUsageModel;
import com.android.ide.common.resources.usage.ResourceUsageModel.Resource;
import com.android.resources.ResourceType;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Streams;
import com.google.common.primitives.Ints;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;

/** Marks resources which are possibly referenced by string constants as reachable. */
public class PossibleResourcesMarker {

    // Copied from StringFormatDetector
    // See java.util.Formatter docs
    public static final Pattern FORMAT =
            Pattern.compile(
                    // Generic format:
                    //   %[argument_index$][flags][width][.precision]conversion
                    //
                    "%"
                            +
                            // Argument Index
                            "(\\d+\\$)?"
                            +
                            // Flags
                            "([-+#, 0(<]*)?"
                            +
                            // Width
                            "(\\d+)?"
                            +
                            // Precision
                            "(\\.\\d+)?"
                            +
                            // Conversion. These are all a single character, except date/time
                            // conversions
                            // which take a prefix of t/T:
                            "([tT])?"
                            +
                            // The current set of conversion characters are
                            // b,h,s,c,d,o,x,e,f,g,a,t (as well as all those as upper-case
                            // characters), plus
                            // n for newlines and % as a literal %. And then there are all the
                            // time/date
                            // characters: HIKLm etc. Just match on all characters here since there
                            // should
                            // be at least one.
                            "([a-zA-Z%])");

    static final String NO_MATCH = "-nomatch-";

    private final ShrinkerDebugReporter debugReporter;
    private final ResourceStore resourceStore;
    private final Set<String> strings;
    private final boolean foundWebContent;

    public PossibleResourcesMarker(ShrinkerDebugReporter debugReporter,
                                   ResourceStore resourceStore,
                                   Set<String> strings,
                                   boolean foundWebContent) {
        this.debugReporter = debugReporter;
        this.resourceStore = resourceStore;
        this.strings = strings;
        this.foundWebContent = foundWebContent;
    }

    public void markPossibleResourcesReachable() {
        Set<String> names =
                resourceStore.getResources().stream()
                        .map(resource -> resource.name)
                        .collect(toImmutableSet());

        int shortest = names.stream().mapToInt(String::length).min().orElse(Integer.MAX_VALUE);

        // Check whether the string looks relevant
        // We consider four types of strings:
        //  (1) simple resource names, e.g. "foo" from @layout/foo
        //      These might be the parameter to a getIdentifier() call, or could
        //      be composed into a fully qualified resource name for the getIdentifier()
        //      method. We match these for *all* resource types.
        //  (2) Relative source names, e.g. layout/foo, from @layout/foo
        //      These might be composed into a fully qualified resource name for
        //      getIdentifier().
        //  (3) Fully qualified resource names of the form package:type/name.
        //  (4) If foundWebContent is true, look for android_res/ URL strings as well
        strings.stream()
                .filter(string -> string.length() >= shortest)
                .flatMap(
                        string -> {
                            int n = string.length();
                            boolean justName = true;
                            boolean formatting = false;
                            boolean haveSlash = false;
                            for (int i = 0; i < n; i++) {
                                char c = string.charAt(i);
                                haveSlash |= c == '/';
                                formatting |= c == '%';
                                justName =
                                        justName && !(c == ':' || c == '%' || c == '/');
                            }

                            Stream<Resource> reachable = Streams.concat(
                                    foundWebContent
                                            ? possibleWebResources(names, string)
                                            : Stream.empty(),
                                    justName ? possiblePrefixMatch(string) : Stream.empty(),
                                    formatting && !haveSlash
                                            ? possibleFormatting(string)
                                            : Stream.empty(),
                                    haveSlash
                                            ? possibleTypedResource(names, string)
                                            : Stream.empty(),
                                    possibleIntResource(string));

                            return reachable
                                    .peek(resource -> debugReporter.debug(() -> "Marking "
                                    + resource + " used because it matches string pool constant "
                                    + string));
                        })
                .forEach(ResourceUsageModel::markReachable);
    }

    private Stream<Resource> possibleWebResources(
            Set<String> names, String string) {
        // Look for android_res/ URL strings.
        List<Resource> resources = resourceStore.getResourcesFromWebUrl(string);
        if (!resources.isEmpty()) {
            return resources.stream();
        }

        int start = Math.max(string.lastIndexOf('/'), 0);
        int dot = string.indexOf('.', start);
        String name = string.substring(start, dot != -1 ? dot : string.length());

        if (names.contains(name)) {
            return resourceStore.getResourceMaps().stream()
                    .filter(map -> map.containsKey(name))
                    .flatMap(map -> map.get(name).stream());
        }
        return Stream.empty();
    }

    private Stream<Resource> possiblePrefixMatch(String string) {
        // Check for a simple prefix match, e.g. as in
        // getResources().getIdentifier("ic_video_codec_" + codecName, "drawable", ...)
        return resourceStore.getResources().stream()
                .filter(resource -> resource.name.startsWith(resourceNameToFieldName(string)));
    }

    private Stream<Resource> possibleFormatting(String string) {
        // Possibly a formatting string, e.g.
        //   String name = String.format("my_prefix_%1d", index);
        //   int res = getContext().getResources().getIdentifier(name, "drawable", ...)
        try {
            Pattern pattern = Pattern.compile(convertFormatStringToRegexp(string));
            return resourceStore.getResources().stream()
                    .filter(resource -> pattern.matcher(resource.name).matches());
        } catch (PatternSyntaxException ignored) {
            return Stream.empty();
        }
    }

    private Stream<Resource> possibleTypedResource(
            Set<String> names, String string) {
        // Try to pick out the resource name pieces; if we can find the
        // resource type unambiguously; if not, just match on names
        int slash = string.indexOf('/');
        String name = resourceNameToFieldName(string.substring(slash + 1));
        if (name.isEmpty() || !names.contains(name)) {
            return Stream.empty();
        }
        // See if have a known specific resource type
        if (slash > 0) {
            int colon = string.indexOf(':');
            String typeName = string.substring(colon + 1, slash);
            ResourceType type = ResourceType.fromClassName(typeName);
            return type != null
                    ? resourceStore.getResources(type, name).stream()
                    : Stream.empty();
        }
        return resourceStore.getResourceMaps().stream()
                .filter(map -> map.containsKey(name))
                .flatMap(map -> map.get(name).stream());
    }

    private Stream<Resource> possibleIntResource(String string) {
        // Just a number? There are cases where it calls getIdentifier by
        // a String number; see for example SuggestionsAdapter in the support
        // library which reports supporting a string like "2130837524" and
        // "android.resource://com.android.alarmclock/2130837524".
        String withoutSlash = string.substring(string.lastIndexOf('/') + 1);
        if (withoutSlash.isEmpty() || !isDigit(withoutSlash.charAt(0))) {
            return Stream.empty();
        }
        Integer id = Ints.tryParse(withoutSlash);
        Resource resource = null;
        if (id != null) {
            resource = resourceStore.getResource(id);
        }
        return resource != null ? Stream.of(resource) : Stream.empty();
    }

    @VisibleForTesting
    static String convertFormatStringToRegexp(String formatString) {
        StringBuilder regexp = new StringBuilder();
        int from = 0;
        boolean hasEscapedLetters = false;
        Matcher matcher = FORMAT.matcher(formatString);
        int length = formatString.length();
        while (matcher.find(from)) {
            int start = matcher.start();
            int end = matcher.end();
            if (start == 0 && end == length) {
                // Don't match if the entire string literal starts with % and ends with
                // the a formatting character, such as just "%d": this just matches absolutely
                // everything and is unlikely to be used in a resource lookup
                return NO_MATCH;
            }
            if (start > from) {
                hasEscapedLetters |= appendEscapedPattern(formatString, regexp, from, start);
            }
            String pattern = ".*";
            String conversion = matcher.group(6);
            String timePrefix = matcher.group(5);

            //noinspection VariableNotUsedInsideIf,StatementWithEmptyBody: for readability.
            if (timePrefix != null) {
                // date notation; just use .* to match these
            } else if (conversion != null && conversion.length() == 1) {
                char type = conversion.charAt(0);
                switch (type) {
                    case 's':
                    case 'S':
                    case 't':
                    case 'T':
                        // Match everything
                        break;
                    case '%':
                        pattern = "%";
                        break;
                    case 'n':
                        pattern = "\n";
                        break;
                    case 'c':
                    case 'C':
                        pattern = ".";
                        break;
                    case 'x':
                    case 'X':
                        pattern = "\\p{XDigit}+";
                        break;
                    case 'd':
                    case 'o':
                        pattern = "\\p{Digit}+";
                        break;
                    case 'b':
                        pattern = "(true|false)";
                        break;
                    case 'B':
                        pattern = "(TRUE|FALSE)";
                        break;
                    case 'h':
                    case 'H':
                        pattern = "(null|\\p{XDigit}+)";
                        break;
                    case 'f':
                        pattern = "-?[\\p{XDigit},.]+";
                        break;
                    case 'e':
                        pattern = "-?\\p{Digit}+[,.]\\p{Digit}+e\\+?\\p{Digit}+";
                        break;
                    case 'E':
                        pattern = "-?\\p{Digit}+[,.]\\p{Digit}+E\\+?\\p{Digit}+";
                        break;
                    case 'a':
                        pattern = "0x[\\p{XDigit},.+p]+";
                        break;
                    case 'A':
                        pattern = "0X[\\p{XDigit},.+P]+";
                        break;
                    case 'g':
                    case 'G':
                        pattern = "-?[\\p{XDigit},.+eE]+";
                        break;
                }

                // Allow space or 0 prefix
                if (!".*".equals(pattern)) {
                    String width = matcher.group(3);
                    //noinspection VariableNotUsedInsideIf
                    if (width != null) {
                        String flags = matcher.group(2);
                        if ("0".equals(flags)) {
                            pattern = "0*" + pattern;
                        } else {
                            pattern = " " + pattern;
                        }
                    }
                }

                // If it's a general .* wildcard which follows a previous .* wildcard,
                // just skip it (e.g. don't convert %s%s into .*.*; .* is enough.)
                int regexLength = regexp.length();
                if (!".*".equals(pattern)
                        || regexLength < 2
                        || regexp.charAt(regexLength - 1) != '*'
                        || regexp.charAt(regexLength - 2) != '.') {
                    regexp.append(pattern);
                }
            }
            from = end;
        }

        if (from < length) {
            hasEscapedLetters |= appendEscapedPattern(formatString, regexp, from, length);
        }

        if (!hasEscapedLetters) {
            // If the regexp contains *only* formatting characters, e.g. "%.0f%d", or
            // if it contains only formatting characters and punctuation, e.g. "%s_%d",
            // don't treat this as a possible resource name pattern string: it is unlikely
            // to be intended for actual resource names, and has the side effect of matching
            // most names.
            return NO_MATCH;
        }

        return regexp.toString();
    }

    /**
     * Appends the characters in the range [from,to> from formatString as escaped regexp characters
     * into the given string builder. Returns true if there were any letters in the appended text.
     */
    private static boolean appendEscapedPattern(
            @NonNull String formatString, @NonNull StringBuilder regexp, int from, int to) {
        regexp.append(Pattern.quote(formatString.substring(from, to)));

        for (int i = from; i < to; i++) {
            if (Character.isLetter(formatString.charAt(i))) {
                return true;
            }
        }

        return false;
    }
}
