/*
 * Copyright (C) 2010 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 vogar;

//import com.google.caliper.internal.gson.stream.JsonReader;

import com.android.json.stream.JsonReader;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import vogar.commands.Command;
import vogar.util.Log;

/**
 * A database of expected outcomes. Entries in this database come in two forms.
 * <ul>
 *   <li>Outcome expectations name an outcome (or its prefix, such as
 *       "java.util"), its expected result, and an optional pattern to match
 *       the expected output.
 *   <li>Failure expectations include a pattern that may match the output of any
 *       outcome. These expectations are useful for hiding failures caused by
 *       cross-cutting features that aren't supported.
 * </ul>
 *
 * <p>If an outcome matches both an outcome expectation and a failure
 * expectation, the outcome expectation will be returned.
 */
public final class ExpectationStore {

    /** The pattern to use when no expected output is specified */
    private static final Pattern MATCH_ALL_PATTERN
            = Pattern.compile(".*", Pattern.MULTILINE | Pattern.DOTALL);

    /** The expectation of a general successful run. */
    private static final Expectation SUCCESS = new Expectation(Result.SUCCESS, MATCH_ALL_PATTERN,
            Collections.<String>emptySet(), "", -1);

    private static final int PATTERN_FLAGS = Pattern.MULTILINE | Pattern.DOTALL;

    private final Map<String, Expectation> outcomes = new LinkedHashMap<String, Expectation>();
    private final Map<String, Expectation> failures = new LinkedHashMap<String, Expectation>();

    private ExpectationStore() {}

    /**
     * Finds the expected result for the specified action or outcome name. This
     * returns a value for all names, even if no explicit expectation was set.
     */
    public Expectation get(String name) {
        Expectation byName = getByNameOrPackage(name);
        return byName != null ? byName : SUCCESS;
    }

    /**
     * Finds the expected result for the specified outcome after it has
     * completed. Unlike {@code get()}, this also takes into account the
     * outcome's output.
     *
     * <p>For outcomes that have both a name match and an output match,
     * exact name matches are preferred, then output matches, then inexact
     * name matches.
     */
    public Expectation get(Outcome outcome) {
        Expectation exactNameMatch = outcomes.get(outcome.getName());
        if (exactNameMatch != null) {
            return exactNameMatch;
        }

        for (Map.Entry<String, Expectation> entry : failures.entrySet()) {
            if (entry.getValue().matches(outcome)) {
                return entry.getValue();
            }
        }

        Expectation byName = getByNameOrPackage(outcome.getName());
        return byName != null ? byName : SUCCESS;
    }

    private Expectation getByNameOrPackage(String name) {
        while (true) {
            Expectation expectation = outcomes.get(name);
            if (expectation != null) {
                return expectation;
            }

            int dotOrHash = Math.max(name.lastIndexOf('.'), name.lastIndexOf('#'));
            if (dotOrHash == -1) {
                return null;
            }

            name = name.substring(0, dotOrHash);
        }
    }

    public static ExpectationStore parse(Set<File> expectationFiles, ModeId mode) throws IOException {
        ExpectationStore result = new ExpectationStore();
        for (File f : expectationFiles) {
            if (f.exists()) {
                result.parse(f, mode);
            }
        }
        return result;
    }

    public void parse(File expectationsFile, ModeId mode) throws IOException {
        Log.verbose("loading expectations file " + expectationsFile);

        int count = 0;
        JsonReader reader = null;
        try {
            reader = new JsonReader(new FileReader(expectationsFile));
            reader.setLenient(true);
            reader.beginArray();
            while (reader.hasNext()) {
                readExpectation(reader, mode);
                count++;
            }
            reader.endArray();

            Log.verbose("loaded " + count + " expectations from " + expectationsFile);
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    private void readExpectation(JsonReader reader, ModeId mode) throws IOException {
        boolean isFailure = false;
        Result result = Result.EXEC_FAILED;
        Pattern pattern = MATCH_ALL_PATTERN;
        Set<String> names = new LinkedHashSet<String>();
        Set<String> tags = new LinkedHashSet<String>();
        Set<ModeId> modes = null;
        String description = "";
        long buganizerBug = -1;

        reader.beginObject();
        while (reader.hasNext()) {
            String name = reader.nextName();
            if (name.equals("result")) {
                result = Result.valueOf(reader.nextString());
            } else if (name.equals("name")) {
                names.add(reader.nextString());
            } else if (name.equals("names")) {
                readStrings(reader, names);
            } else if (name.equals("failure")) {
                // isFailure is somewhat arbitrarily keyed on the existence of a "failure"
                // element instead of looking at the "result" field. There are only about 5
                // expectations in our entire expectation store that have this tag.
                //
                // TODO: Get rid of it and the "failures" map and just use the outcomes
                // map for everything. Both uses seem useless.
                isFailure = true;
                names.add(reader.nextString());
            } else if (name.equals("pattern")) {
                pattern = Pattern.compile(reader.nextString(), PATTERN_FLAGS);
            } else if (name.equals("substring")) {
                pattern = Pattern.compile(".*" + Pattern.quote(reader.nextString()) + ".*", PATTERN_FLAGS);
            } else if (name.equals("tags")) {
                readStrings(reader, tags);
            } else if (name.equals("description")) {
                Iterable<String> split = Splitter.on("\n").omitEmptyStrings().trimResults().split(reader.nextString());
                description = Joiner.on("\n").join(split);
            } else if (name.equals("bug")) {
                buganizerBug = reader.nextLong();
            } else if (name.equals("modes")) {
                modes = readModes(reader);
            } else {
                Log.warn("Unhandled name in expectations file: " + name);
                reader.skipValue();
            }
        }
        reader.endObject();

        if (names.isEmpty()) {
            throw new IllegalArgumentException("Missing 'name' or 'failure' key in " + reader);
        }
        if (modes != null && !modes.contains(mode)) {
            return;
        }

        Expectation expectation = new Expectation(result, pattern, tags, description, buganizerBug);
        Map<String, Expectation> map = isFailure ? failures : outcomes;
        for (String name : names) {
            if (map.put(name, expectation) != null) {
                throw new IllegalArgumentException("Duplicate expectations for " + name);
            }
        }
    }

    private void readStrings(JsonReader reader, Set<String> output) throws IOException {
        reader.beginArray();
        while (reader.hasNext()) {
            output.add(reader.nextString());
        }
        reader.endArray();
    }

    private Set<ModeId> readModes(JsonReader reader) throws IOException {
        Set<ModeId> result = new LinkedHashSet<ModeId>();
        reader.beginArray();
        while (reader.hasNext()) {
            result.add(ModeId.valueOf(reader.nextString().toUpperCase()));
        }
        reader.endArray();
        return result;
    }

    /**
     * Sets the bugIsOpen status on all expectations by querying an external bug
     * tracker.
     */
    public void loadBugStatuses(String openBugsCommand) {
        Iterable<Expectation> allExpectations = Iterables.concat(outcomes.values(), failures.values());

        // figure out what bug IDs we're interested in
        Set<String> bugs = new LinkedHashSet<String>();
        for (Expectation expectation : allExpectations) {
            if (expectation.getBug() != -1) {
                bugs.add(Long.toString(expectation.getBug()));
            }
        }
        if (bugs.isEmpty()) {
            return;
        }

        // query the external app for open bugs
        List<String> openBugs = new Command.Builder()
                .args(openBugsCommand)
                .args(bugs)
                .execute();
        Set<Long> openBugsSet = new LinkedHashSet<Long>();
        for (String bug : openBugs) {
            openBugsSet.add(Long.parseLong(bug));
        }

        Log.verbose("tracking " + openBugsSet.size() + " open bugs: " + openBugs);

        // update our expectations with that set
        for (Expectation expectation : allExpectations) {
            if (openBugsSet.contains(expectation.getBug())) {
                expectation.setBugIsOpen(true);
            }
        }
    }
}
