/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.flex.abc;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.HashSet;
import java.util.Set;

import org.apache.flex.abc.semantics.InstanceInfo;
import org.apache.flex.abc.semantics.Name;

/**
 * ClassDependencySort contains data structures and algorithms to sort a list of
 * classes into dependency order.
 */
public abstract class ClassDependencySort
{
    /**
     * The objects being sorted need to show an InstanceInfo.
     */
    public static interface IInstanceInfoProvider
    {
        public InstanceInfo getInstanceInfo();
    }

    /**
     * Perform a topological sort by inheritance.
     * 
     * @return a Collection of classes, sorted so that classes appear before
     * their superclasses or inherited interfaces.
     * @throws IllegalStateException if there are circular dependencies.
     */
    public static <T extends IInstanceInfoProvider> Collection<T> getSorted(Collection<T> classes)
    {
        ArrayList<T> sortedClasses = new ArrayList<T>();

        //  First establish dependency relationships between classes.
        ArrayList<DependencyTracker<T>> workingSet = new ArrayList<DependencyTracker<T>>();
        for (T raw_x : classes)
        {
            DependencyTracker<T> x = new DependencyTracker<T>(raw_x);
            for (DependencyTracker<T> y : workingSet)
                x.establishDependency(y);
            workingSet.add(x);
        }

        //  Perform a simple set-oriented topological sort:
        //  yield any class that has no dependencies,remove
        //  that class from its dependents' dependencies, 
        //  iterate until done.
        boolean classProcessed;

        do
        {
            classProcessed = false;

            Iterator<DependencyTracker<T>> it = workingSet.iterator();
            while (it.hasNext())
            {
                DependencyTracker<T> n = it.next();

                if (n.dependencies.isEmpty())
                {
                    classProcessed = true;
                    sortedClasses.add(n.payload);

                    //  Remove this dependency from dependents' graphs.
                    for (DependencyTracker<T> dep : n.dependents)
                        dep.dependencies.remove(n);

                    it.remove();
                }
            }
        }
        while (classProcessed);

        if (!workingSet.isEmpty())
            throw new IllegalStateException("cycle in class dependency graph");

        return sortedClasses;
    }

    /**
     * Track the dependency relationships of an object being sorted.
     */
    static class DependencyTracker<T extends IInstanceInfoProvider>
    {
        /**
         * @param payload - the object to be sorted.
         */
        DependencyTracker(T payload)
        {
            this.payload = payload;
        }

        /**
         * The object being sorted.
         */
        T payload;

        /**
         * The set of objects that depend on this.payload
         */
        Set<DependencyTracker<T>> dependents = new HashSet<DependencyTracker<T>>();

        /**
         * The set of objects that this.payload depends upon.
         */
        Set<DependencyTracker<T>> dependencies = new HashSet<DependencyTracker<T>>();

        /**
         * Establish dependency relationships between this node and another.
         */
        void establishDependency(DependencyTracker<T> other)
        {
            InstanceInfo myInstance = this.payload.getInstanceInfo();
            InstanceInfo otherInstance = other.payload.getInstanceInfo();

            if (myInstance.superName != null && myInstance.superName.equals(otherInstance.name))
                this.makeDependentOf(other);
            else if (otherInstance.superName != null && otherInstance.superName.equals(myInstance.name))
                other.makeDependentOf(this);

            for (Name myInterface : myInstance.interfaceNames)
            {
                if (myInterface != null && myInterface.equals(otherInstance.name))
                    this.makeDependentOf(other);
            }

            for (Name otherInterface : otherInstance.interfaceNames)
            {
                if (otherInterface.equals(myInstance.name))
                    other.makeDependentOf(this);
            }

            if (this.dependencies.contains(other) && other.dependencies.contains(this))
            {
                throw new IllegalStateException("simple cycle in dependency graph");
            }
        }

        /**
         * Note that another object is dependent on this.payload.
         * 
         * @param other - the DependencyTracker tracking the other object.
         */
        void makeDependentOf(DependencyTracker<T> other)
        {
            assert other != this;
            this.dependencies.add(other);
            other.dependents.add(this);
        }
    }
}
