/**
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * <p>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
 *
 * <p>http://www.apache.org/licenses/LICENSE-2.0
 *
 * <p>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.vts.util;

import com.android.vts.entity.DeviceInfoEntity;
import com.android.vts.entity.ProfilingPointRunEntity;
import com.android.vts.entity.TestRunEntity;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;

/** FilterUtil, a helper class for parsing and matching search queries to data. */
public class FilterUtil {
    protected static final Logger logger = Logger.getLogger(FilterUtil.class.getName());
    private static final String INEQUALITY_REGEX = "(<=|>=|<|>|=)";

    /** Key class to represent a filter token. */
    public enum FilterKey {
        DEVICE_BUILD_ID("deviceBuildId", DeviceInfoEntity.BUILD_ID, true),
        BRANCH("branch", DeviceInfoEntity.BRANCH, true),
        TARGET("device", DeviceInfoEntity.BUILD_FLAVOR, true),
        VTS_BUILD_ID("testBuildId", TestRunEntity.TEST_BUILD_ID, false),
        HOSTNAME("hostname", TestRunEntity.HOST_NAME, false),
        PASSING("passing", TestRunEntity.PASS_COUNT, false),
        NONPASSING("nonpassing", TestRunEntity.FAIL_COUNT, false);

        private static final Map<String, FilterKey> keyMap;

        static {
            keyMap = new HashMap<>();
            for (FilterKey k : EnumSet.allOf(FilterKey.class)) {
                keyMap.put(k.keyString, k);
            }
        }

        /**
         * Test if a string is a valid device key.
         *
         * @param keyString The key string.
         * @return True if they key string matches a key and the key is a device filter.
         */
        public static boolean isDeviceKey(String keyString) {
            return keyMap.containsKey(keyString) && keyMap.get(keyString).isDevice;
        }

        /**
         * Test if a string is a valid test key.
         *
         * @param keyString The key string.
         * @return True if they key string matches a key and the key is a test filter.
         */
        public static boolean isTestKey(String keyString) {
            return keyMap.containsKey(keyString) && !keyMap.get(keyString).isDevice;
        }

        /**
         * Parses a key string into a key.
         *
         * @param keyString The key string.
         * @return The key matching the key string.
         */
        public static FilterKey parse(String keyString) {
            return keyMap.get(keyString);
        }

        private final String keyString;
        private final String property;
        private final boolean isDevice;

        /**
         * Constructs a key with the specified key string.
         *
         * @param keyString The identifying key string.
         * @param propertyName The name of the property to match.
         */
        private FilterKey(String keyString, String propertyName, boolean isDevice) {
            this.keyString = keyString;
            this.property = propertyName;
            this.isDevice = isDevice;
        }

        /**
         * Return a filter predicate for string equality.
         *
         * @param matchString The string to match.
         * @return A filter predicate enforcing equality on the property.
         */
        public FilterPredicate getFilterForString(String matchString) {
            return new FilterPredicate(this.property, FilterOperator.EQUAL, matchString);
        }

        /**
         * Return a filter predicate for number inequality or equality.
         *
         * @param matchNumber A string, either a number or an inequality symbol followed by a
         *     number.
         * @return A filter predicate enforcing equality on the property, or null if invalid.
         */
        public FilterPredicate getFilterForNumber(String matchNumber) {
            String numberString = matchNumber.trim();
            Pattern p = Pattern.compile(INEQUALITY_REGEX);
            Matcher m = p.matcher(numberString);

            // Default operator is equality.
            FilterOperator op = FilterOperator.EQUAL;

            // Determine if there is an inequality operator.
            if (m.find() && m.start() == 0 && m.end() != numberString.length()) {
                String opString = m.group();

                // Inequality operator can be <=, <, >, >=, or =.
                if (opString.equals("<=")) {
                    op = FilterOperator.LESS_THAN_OR_EQUAL;
                } else if (opString.equals("<")) {
                    op = FilterOperator.LESS_THAN;
                } else if (opString.equals(">")) {
                    op = FilterOperator.GREATER_THAN;
                } else if (opString.equals(">=")) {
                    op = FilterOperator.GREATER_THAN_OR_EQUAL;
                } else if (!opString.equals("=")) { // unrecognized inequality.
                    return null;
                }
                numberString = matchNumber.substring(m.end()).trim();
            }
            try {
                long number = Long.parseLong(numberString);
                return new FilterPredicate(this.property, op, number);
            } catch (NumberFormatException e) {
                // invalid number
                return null;
            }
        }

        /**
         * Get the enum value
         *
         * @return The string value associated with the key.
         */
        public String getValue() {
            return this.keyString;
        }
    }

    /**
     * Get the common elements among multiple collections.
     *
     * @param collections The collections containing all sub collections to find common element.
     * @return The common elements set found from the collections param.
     */
    public static <T> Set<T> getCommonElements(Collection<? extends Collection<T>> collections) {

        Set<T> common = new LinkedHashSet<T>();
        if (!collections.isEmpty()) {
            Iterator<? extends Collection<T>> iterator = collections.iterator();
            common.addAll(iterator.next());
            while (iterator.hasNext()) {
                common.retainAll(iterator.next());
            }
        }
        return common;
    }

    /**
     * Get the first value associated with the key in the parameter map.
     *
     * @param parameterMap The parameter map with string keys and (Object) String[] values.
     * @param key The key whose value to get.
     * @return The first value associated with the provided key.
     */
    public static String getFirstParameter(Map<String, String[]> parameterMap, String key) {
        String[] values = (String[]) parameterMap.get(key);
        if (values.length == 0) return null;
        return values[0];
    }

    /**
     * Get a filter on devices from a user search query.
     *
     * @param parameterMap The key-value map of url parameters.
     * @return A filter with the values from the user search parameters.
     */
    public static Filter getUserDeviceFilter(Map<String, String[]> parameterMap) {
        Filter deviceFilter = null;
        for (String key : parameterMap.keySet()) {
            if (!FilterKey.isDeviceKey(key)) continue;
            String value = getFirstParameter(parameterMap, key);
            if (value == null) continue;
            FilterKey filterKey = FilterKey.parse(key);
            Filter f = filterKey.getFilterForString(value);
            if (deviceFilter == null) {
                deviceFilter = f;
            } else {
                deviceFilter = CompositeFilterOperator.and(deviceFilter, f);
            }
        }
        return deviceFilter;
    }

    /**
     * Get a list of test filters given the user parameters.
     *
     * @param parameterMap The key-value map of url parameters.
     * @return A list of filters, each having at most one inequality filter.
     */
    public static List<Filter> getUserTestFilters(Map<String, String[]> parameterMap) {
        List<Filter> userFilters = new ArrayList<>();
        for (String key : parameterMap.keySet()) {
            if (!FilterKey.isTestKey(key)) continue;
            String stringValue = getFirstParameter(parameterMap, key);
            if (stringValue == null) continue;
            FilterKey filterKey = FilterKey.parse(key);
            switch (filterKey) {
                case NONPASSING:
                case PASSING:
                    userFilters.add(filterKey.getFilterForNumber(stringValue));
                    break;
                case HOSTNAME:
                case VTS_BUILD_ID:
                    userFilters.add(filterKey.getFilterForString(stringValue.toLowerCase()));
                    break;
                default:
                    continue;
            }
        }
        return userFilters;
    }

    /**
     * Get a filter on the test run type.
     *
     * @param showPresubmit True to display presubmit tests.
     * @param showPostsubmit True to display postsubmit tests.
     * @param unfiltered True if no filtering should be applied.
     * @return A filter on the test type.
     */
    public static Filter getTestTypeFilter(
            boolean showPresubmit, boolean showPostsubmit, boolean unfiltered) {
        if (unfiltered) {
            return null;
        } else if (showPresubmit && !showPostsubmit) {
            return new FilterPredicate(
                    TestRunEntity.TYPE,
                    FilterOperator.EQUAL,
                    TestRunEntity.TestRunType.PRESUBMIT.getNumber());
        } else if (showPostsubmit && !showPresubmit) {
            return new FilterPredicate(
                    TestRunEntity.TYPE,
                    FilterOperator.EQUAL,
                    TestRunEntity.TestRunType.POSTSUBMIT.getNumber());
        } else {
            List<Integer> types = new ArrayList<>();
            types.add(TestRunEntity.TestRunType.PRESUBMIT.getNumber());
            types.add(TestRunEntity.TestRunType.POSTSUBMIT.getNumber());
            return new FilterPredicate(TestRunEntity.TYPE, FilterOperator.IN, types);
        }
    }

    /**
     * Get a filter for profiling points between a specified time window.
     *
     * @param grandparentKey The key of the profiling point grandparent entity.
     * @param parentKind The kind of the profiling point parent.
     * @param startTime The start time of the window, or null if unbounded.
     * @param endTime The end time of the window, or null if unbounded.
     * @return A filter to query for profiling points in the time window.
     */
    public static Filter getProfilingTimeFilter(
            Key grandparentKey, String parentKind, Long startTime, Long endTime) {
        if (startTime == null && endTime == null) {
            endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
        }
        Filter startFilter = null;
        Filter endFilter = null;
        Filter filter = null;
        if (startTime != null) {
            Key minRunKey = KeyFactory.createKey(grandparentKey, parentKind, startTime);
            Key startKey =
                    KeyFactory.createKey(
                            minRunKey, ProfilingPointRunEntity.KIND, String.valueOf((char) 0x0));
            startFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.GREATER_THAN_OR_EQUAL,
                            startKey);
            filter = startFilter;
        }
        if (endTime != null) {
            Key maxRunKey = KeyFactory.createKey(grandparentKey, parentKind, endTime);
            Key endKey =
                    KeyFactory.createKey(
                            maxRunKey, ProfilingPointRunEntity.KIND, String.valueOf((char) 0xff));
            endFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.LESS_THAN_OR_EQUAL,
                            endKey);
            filter = endFilter;
        }
        if (startFilter != null && endFilter != null) {
            filter = CompositeFilterOperator.and(startFilter, endFilter);
        }
        return filter;
    }

    /**
     * Get a filter for device information between a specified time window.
     *
     * @param grandparentKey The key of the device's grandparent entity.
     * @param parentKind The kind of the device's parent.
     * @param startTime The start time of the window, or null if unbounded.
     * @param endTime The end time of the window, or null if unbounded.
     * @return A filter to query for devices in the time window.
     */
    public static Filter getDeviceTimeFilter(
            Key grandparentKey, String parentKind, Long startTime, Long endTime) {
        if (startTime == null && endTime == null) {
            endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
        }
        Filter startFilter = null;
        Filter endFilter = null;
        Filter filter = null;
        if (startTime != null) {
            Key minRunKey = KeyFactory.createKey(grandparentKey, parentKind, startTime);
            Key startKey = KeyFactory.createKey(minRunKey, DeviceInfoEntity.KIND, 1);
            startFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.GREATER_THAN_OR_EQUAL,
                            startKey);
            filter = startFilter;
        }
        if (endTime != null) {
            Key maxRunKey = KeyFactory.createKey(grandparentKey, parentKind, endTime);
            Key endKey = KeyFactory.createKey(maxRunKey, DeviceInfoEntity.KIND, Long.MAX_VALUE);
            endFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.LESS_THAN_OR_EQUAL,
                            endKey);
            filter = endFilter;
        }
        if (startFilter != null && endFilter != null) {
            filter = CompositeFilterOperator.and(startFilter, endFilter);
        }
        return filter;
    }

    /**
     * Get the time range filter to apply to a query.
     *
     * @param testKey The key of the parent TestEntity object.
     * @param kind The kind to use for the filters.
     * @param startTime The start time in microseconds, or null if unbounded.
     * @param endTime The end time in microseconds, or null if unbounded.
     * @param testRunFilter The existing filter on test runs to apply, or null.
     * @return A filter to apply on test runs.
     */
    public static Filter getTimeFilter(
            Key testKey, String kind, Long startTime, Long endTime, Filter testRunFilter) {
        if (startTime == null && endTime == null) {
            endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
        }

        Filter startFilter = null;
        Filter endFilter = null;
        Filter filter = null;
        if (startTime != null) {
            Key startKey = KeyFactory.createKey(testKey, kind, startTime);
            startFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.GREATER_THAN_OR_EQUAL,
                            startKey);
            filter = startFilter;
        }
        if (endTime != null) {
            Key endKey = KeyFactory.createKey(testKey, kind, endTime);
            endFilter =
                    new FilterPredicate(
                            Entity.KEY_RESERVED_PROPERTY,
                            FilterOperator.LESS_THAN_OR_EQUAL,
                            endKey);
            filter = endFilter;
        }
        if (startFilter != null && endFilter != null) {
            filter = CompositeFilterOperator.and(startFilter, endFilter);
        }
        if (testRunFilter != null) {
            filter = CompositeFilterOperator.and(filter, testRunFilter);
        }
        return filter;
    }

    public static Filter getTimeFilter(Key testKey, String kind, Long startTime, Long endTime) {
        return getTimeFilter(testKey, kind, startTime, endTime, null);
    }

    /**
     * Get the list of keys matching the provided test filter and device filter.
     *
     * @param ancestorKey The ancestor key to use in the query.
     * @param kind The entity kind to use in the test query.
     * @param testFilters The filter list to apply to test runs (each having <=1 inequality filter).
     * @param deviceFilter The filter to apply to associated devices.
     * @param dir The sort direction of the returned list.
     * @param maxSize The maximum number of entities to return.
     * @return a list of keys matching the provided test and device filters.
     */
    public static List<Key> getMatchingKeys(
            Key ancestorKey,
            String kind,
            List<Filter> testFilters,
            Filter deviceFilter,
            Query.SortDirection dir,
            int maxSize) {
        DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
        Set<Key> matchingTestKeys = null;
        Key minKey = null;
        Key maxKey = null;
        for (Filter testFilter : testFilters) {
            Query testQuery =
                    new Query(kind).setAncestor(ancestorKey).setFilter(testFilter).setKeysOnly();
            Set<Key> filterMatches = new HashSet<>();
            FetchOptions ops = DatastoreHelper.getLargeBatchOptions();
            if (deviceFilter == null && testFilters.size() == 1) {
                ops.limit(maxSize);
                testQuery.addSort(Entity.KEY_RESERVED_PROPERTY, dir);
            }
            logger.log(Level.INFO, "testQuery => " + testQuery);
            for (Entity testRunKey : datastore.prepare(testQuery).asIterable(ops)) {
                filterMatches.add(testRunKey.getKey());
                if (maxKey == null || testRunKey.getKey().compareTo(maxKey) > 0)
                    maxKey = testRunKey.getKey();
                if (minKey == null || testRunKey.getKey().compareTo(minKey) < 0)
                    minKey = testRunKey.getKey();
            }
            if (matchingTestKeys == null) {
                matchingTestKeys = filterMatches;
            } else {
                matchingTestKeys = Sets.intersection(matchingTestKeys, filterMatches);
            }
        }
        logger.log(Level.INFO, "matchingTestKeys => " + matchingTestKeys);

        Set<Key> allMatchingKeys;
        if (deviceFilter == null || matchingTestKeys.size() == 0) {
            allMatchingKeys = matchingTestKeys;
        } else {
            deviceFilter =
                    CompositeFilterOperator.and(
                            deviceFilter,
                            getDeviceTimeFilter(
                                    minKey.getParent(),
                                    minKey.getKind(),
                                    minKey.getId(),
                                    maxKey.getId()));
            allMatchingKeys = new HashSet<>();
            Query deviceQuery =
                    new Query(DeviceInfoEntity.KIND)
                            .setAncestor(ancestorKey)
                            .setFilter(deviceFilter)
                            .setKeysOnly();
            for (Entity device :
                    datastore
                            .prepare(deviceQuery)
                            .asIterable(DatastoreHelper.getLargeBatchOptions())) {
                if (matchingTestKeys.contains(device.getKey().getParent())) {
                    allMatchingKeys.add(device.getKey().getParent());
                }
            }
        }
        logger.log(Level.INFO, "allMatchingKeys => " + allMatchingKeys);
        List<Key> gets = new ArrayList<>(allMatchingKeys);
        if (dir == Query.SortDirection.DESCENDING) {
            gets.sort(Comparator.reverseOrder());
        } else {
            gets.sort(Comparator.naturalOrder());
        }
        gets = gets.subList(0, Math.min(gets.size(), maxSize));
        return gets;
    }

    /**
     * Set the request with the provided key/value attribute map.
     *
     * @param request The request whose attributes to set.
     * @param parameterMap The map from key to (Object) String[] value whose entries to parse.
     */
    public static void setAttributes(HttpServletRequest request, Map<String, String[]> parameterMap) {
        for (String key : parameterMap.keySet()) {
            if (!FilterKey.isDeviceKey(key) && !FilterKey.isTestKey(key)) continue;
            FilterKey filterKey = FilterKey.parse(key);
            String[] values = parameterMap.get(key);
            if (values.length == 0) continue;
            String stringValue = values[0];
            request.setAttribute(filterKey.keyString, new Gson().toJson(stringValue));
        }
    }
}
