/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.sjavac;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * The build state class captures the source code and generated artifacts
 * from a build. There are usually two build states, the previous one (prev),
 * loaded from the javac_state file, and the current one (now).
 *
 * <p><b>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own
 * risk.  This code and its internal interfaces are subject to change
 * or deletion without notice.</b></p>
 */
public class BuildState {
    private Map<String,Module> modules = new HashMap<>();
    private Map<String,Package> packages = new HashMap<>();
    private Map<String,Source> sources = new HashMap<>();
    private Map<String,File> artifacts = new HashMap<>();
    // Map from package to a set of packages that depend on said package.
    private Map<String,Set<String>> dependents = new HashMap<>();

    public  Map<String,Module> modules() { return modules; }
    public  Map<String,Package> packages() { return packages; }
    public  Map<String,Source> sources() { return sources; }
    public  Map<String,File> artifacts() { return artifacts; }
    public  Map<String,Set<String>> dependents() { return dependents; }

    /**
     * Lookup a module from a name. Create the module if it does
     * not exist yet.
     */
    public Module lookupModule(String mod) {
        Module m = modules.get(mod);
        if (m == null) {
            m = new Module(mod, "???");
            modules.put(mod, m);
        }
        return m;
    }

    /**
     * Find a module from a given package name. For example:
     * The package name "base:java.lang" will fetch the module named "base".
     * The package name ":java.net" will fetch the default module.
     */
    Module findModuleFromPackageName(String pkg) {
        int cp = pkg.indexOf(':');
        assert(cp != -1);
        String mod = pkg.substring(0, cp);
        return lookupModule(mod);
    }

    /**
     * Store references to all packages, sources and artifacts for all modules
     * into the build state. I.e. flatten the module tree structure
     * into global maps stored in the BuildState for easy access.
     *
     * @param m The set of modules.
     */
    public void flattenPackagesSourcesAndArtifacts(Map<String,Module> m) {
        modules = m;
        // Extract all the found packages.
        for (Module i : modules.values()) {
            for (Map.Entry<String,Package> j : i.packages().entrySet()) {
                Package p = packages.get(j.getKey());
                // Check that no two different packages are stored under same name.
                assert(p == null || p == j.getValue());
                if (p == null) {
                    p = j.getValue();
                    packages.put(j.getKey(),j.getValue());
                }
                for (Map.Entry<String,Source> k : p.sources().entrySet()) {
                    Source s = sources.get(k.getKey());
                    // Check that no two different sources are stored under same name.
                    assert(s == null || s == k.getValue());
                    if (s == null) {
                        s = k.getValue();
                        sources.put(k.getKey(), k.getValue());
                    }
                }
                for (Map.Entry<String,File> g : p.artifacts().entrySet()) {
                    File f = artifacts.get(g.getKey());
                    // Check that no two artifacts are stored under the same file.
                    assert(f == null || f == g.getValue());
                    if (f == null) {
                        f = g.getValue();
                        artifacts.put(g.getKey(), g.getValue());
                    }
                }
            }
        }
    }

    /**
     * Store references to all artifacts found in the module tree into the maps
     * stored in the build state.
     *
     * @param m The set of modules.
     */
    public void flattenArtifacts(Map<String,Module> m) {
        modules = m;
        // Extract all the found packages.
        for (Module i : modules.values()) {
            for (Map.Entry<String,Package> j : i.packages().entrySet()) {
                Package p = packages.get(j.getKey());
                // Check that no two different packages are stored under same name.
                assert(p == null || p == j.getValue());
                p = j.getValue();
                packages.put(j.getKey(),j.getValue());
                for (Map.Entry<String,File> g : p.artifacts().entrySet()) {
                    File f = artifacts.get(g.getKey());
                    // Check that no two artifacts are stored under the same file.
                    assert(f == null || f == g.getValue());
                    artifacts.put(g.getKey(), g.getValue());
                }
            }
        }
    }

    /**
     * Calculate the package dependents (ie the reverse of the dependencies).
     */
    public void calculateDependents() {
        dependents = new HashMap<>();
        for (String s : packages.keySet()) {
            Package p = packages.get(s);
            for (String d : p.dependencies()) {
                Set<String> ss = dependents.get(d);
                if (ss == null) {
                    ss = new HashSet<>();
                    dependents.put(d, ss);
                }
                // Add the dependent information to the global dependent map.
                ss.add(s);
                Package dp = packages.get(d);
                // Also add the dependent information to the package specific map.
                // Normally, you do not compile java.lang et al. Therefore
                // there are several packages that p depends upon that you
                // do not have in your state database. This is perfectly fine.
                if (dp != null) {
                    // But this package did exist in the state database.
                    dp.addDependent(p.name());
                }
            }
        }
    }

    /**
     * Verify that the setModules method above did the right thing when
     * running through the module->package->source structure.
     */
    public void checkInternalState(String msg, boolean linkedOnly, Map<String,Source> srcs) {
        boolean baad = false;
        Map<String,Source> original = new HashMap<>();
        Map<String,Source> calculated = new HashMap<>();

        for (String s : sources.keySet()) {
            Source ss = sources.get(s);
            if (ss.isLinkedOnly() == linkedOnly) {
                calculated.put(s,ss);
            }
        }
        for (String s : srcs.keySet()) {
            Source ss = srcs.get(s);
            if (ss.isLinkedOnly() == linkedOnly) {
                original.put(s,ss);
            }
        }
        if (original.size() != calculated.size()) {
            Log.error("INTERNAL ERROR "+msg+" original and calculated are not the same size!");
            baad = true;
        }
        if (!original.keySet().equals(calculated.keySet())) {
            Log.error("INTERNAL ERROR "+msg+" original and calculated do not have the same domain!");
            baad = true;
        }
        if (!baad) {
            for (String s : original.keySet()) {
                Source s1 = original.get(s);
                Source s2 = calculated.get(s);
                if (s1 == null || s2 == null || !s1.equals(s2)) {
                    Log.error("INTERNAL ERROR "+msg+" original and calculated have differing elements for "+s);
                }
                baad = true;
            }
        }
        if (baad) {
            for (String s : original.keySet()) {
                Source ss = original.get(s);
                Source sss = calculated.get(s);
                if (sss == null) {
                    Log.error("The file "+s+" does not exist in calculated tree of sources.");
                }
            }
            for (String s : calculated.keySet()) {
                Source ss = calculated.get(s);
                Source sss = original.get(s);
                if (sss == null) {
                    Log.error("The file "+s+" does not exist in original set of found sources.");
                }
            }
        }
    }

    /**
     * Load a module from the javac state file.
     */
    public Module loadModule(String l) {
        Module m = Module.load(l);
        modules.put(m.name(), m);
        return m;
    }

    /**
     * Load a package from the javac state file.
     */
    public Package loadPackage(Module lastModule, String l) {
        Package p = Package.load(lastModule, l);
        lastModule.addPackage(p);
        packages.put(p.name(), p);
        return p;
    }

    /**
     * Load a source from the javac state file.
     */
    public Source loadSource(Package lastPackage, String l, boolean is_generated) {
        Source s = Source.load(lastPackage, l, is_generated);
        lastPackage.addSource(s);
        sources.put(s.name(), s);
        return s;
    }

    /**
     * During an incremental compile we need to copy the old javac state
     * information about packages that were not recompiled.
     */
    public void copyPackagesExcept(BuildState prev, Set<String> recompiled, Set<String> removed) {
        for (String pkg : prev.packages().keySet()) {
            // Do not copy recompiled or removed packages.
            if (recompiled.contains(pkg) || removed.contains(pkg)) continue;
            Module mnew = findModuleFromPackageName(pkg);
            Package pprev = prev.packages().get(pkg);
            mnew.addPackage(pprev);
            // Do not forget to update the flattened data.
            packages.put(pkg, pprev);
        }
    }
}
