/*
 * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @author Charlton Innovations, Inc.
 */

package sun.java2d.loops;

import java.util.Comparator;
import java.util.Arrays;
import sun.java2d.SunGraphics2D;

/**
 *   GraphicsComponentMgr provides services to
 *   1. register primitives for later use
 *   2. locate an instance of a primitve based on characteristics
 */
public final class GraphicsPrimitiveMgr {

    private static final boolean debugTrace = false;
    private static GraphicsPrimitive primitives[];
    private static GraphicsPrimitive generalPrimitives[];
    private static boolean needssort = true;

    private static native void initIDs(Class GP, Class ST, Class CT,
                                       Class SG2D, Class Color, Class AT,
                                       Class XORComp, Class AlphaComp,
                                       Class Path2D, Class Path2DFloat,
                                       Class SHints);
    private static native void registerNativeLoops();

    static {
        initIDs(GraphicsPrimitive.class,
                SurfaceType.class,
                CompositeType.class,
                SunGraphics2D.class,
                java.awt.Color.class,
                java.awt.geom.AffineTransform.class,
                XORComposite.class,
                java.awt.AlphaComposite.class,
                java.awt.geom.Path2D.class,
                java.awt.geom.Path2D.Float.class,
                sun.awt.SunHints.class);
        CustomComponent.register();
        GeneralRenderer.register();
        registerNativeLoops();
    }

    private static class PrimitiveSpec {
        public int uniqueID;
    }

    private static Comparator primSorter = new Comparator() {
        public int compare(Object o1, Object o2) {
            int id1 = ((GraphicsPrimitive) o1).getUniqueID();
            int id2 = ((GraphicsPrimitive) o2).getUniqueID();

            return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
        }
    };

    private static Comparator primFinder = new Comparator() {
        public int compare(Object o1, Object o2) {
            int id1 = ((GraphicsPrimitive) o1).getUniqueID();
            int id2 = ((PrimitiveSpec) o2).uniqueID;

            return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
        }
    };

    /**
     * Ensure that noone can instantiate this class.
     */
    private GraphicsPrimitiveMgr() {
    }

    public synchronized static void register(GraphicsPrimitive[] newPrimitives)
    {
        GraphicsPrimitive[] devCollection = primitives;
        int oldSize = 0;
        int newSize = newPrimitives.length;
        if (debugTrace) {
            writeLog("Registering " + newSize + " primitives");
            for (int i = 0; i < newSize; i++) {
                writeLog(newPrimitives[i].toString());
            }
        }
        if (devCollection != null) {
            oldSize = devCollection.length;
        }
        GraphicsPrimitive[] temp = new GraphicsPrimitive[oldSize + newSize];
        if (devCollection != null) {
            System.arraycopy(devCollection, 0, temp, 0, oldSize);
        }
        System.arraycopy(newPrimitives, 0, temp, oldSize, newSize);
        needssort = true;
        primitives = temp;
    }

    public synchronized static void registerGeneral(GraphicsPrimitive gen) {
        if (generalPrimitives == null) {
            generalPrimitives = new GraphicsPrimitive[] {gen};
            return;
        }
        int len = generalPrimitives.length;
        GraphicsPrimitive[] newGen = new GraphicsPrimitive[len + 1];
        System.arraycopy(generalPrimitives, 0, newGen, 0, len);
        newGen[len] = gen;
        generalPrimitives = newGen;
    }

    public synchronized static GraphicsPrimitive locate(int primTypeID,
                                                        SurfaceType dsttype)
    {
        return locate(primTypeID,
                      SurfaceType.OpaqueColor,
                      CompositeType.Src,
                      dsttype);
    }

    public synchronized static GraphicsPrimitive locate(int primTypeID,
                                                        SurfaceType srctype,
                                                        CompositeType comptype,
                                                        SurfaceType dsttype)
    {
        /*
          System.out.println("Looking for:");
          System.out.println("    method: "+signature);
          System.out.println("    from:   "+srctype);
          System.out.println("    by:     "+comptype);
          System.out.println("    to:     "+dsttype);
        */
        GraphicsPrimitive prim = locatePrim(primTypeID,
                                            srctype, comptype, dsttype);

        if (prim == null) {
            //System.out.println("Trying general loop");
            prim = locateGeneral(primTypeID);
            if (prim != null) {
                prim = prim.makePrimitive(srctype, comptype, dsttype);
                if (prim != null && GraphicsPrimitive.traceflags != 0) {
                    prim = prim.traceWrap();
                }
            }
        }
        return prim;
    }

    public synchronized static GraphicsPrimitive
        locatePrim(int primTypeID,
                   SurfaceType srctype,
                   CompositeType comptype,
                   SurfaceType dsttype)
    {
        /*
          System.out.println("Looking for:");
          System.out.println("    method: "+signature);
          System.out.println("    from:   "+srctype);
          System.out.println("    by:     "+comptype);
          System.out.println("    to:     "+dsttype);
        */
        SurfaceType src, dst;
        CompositeType cmp;
        GraphicsPrimitive prim;
        PrimitiveSpec spec = new PrimitiveSpec();

        for (dst = dsttype; dst != null; dst = dst.getSuperType()) {
            for (src = srctype; src != null; src = src.getSuperType()) {
                for (cmp = comptype; cmp != null; cmp = cmp.getSuperType()) {
                    /*
                      System.out.println("Trying:");
                      System.out.println("    method: "+spec.methodSignature);
                      System.out.println("    from:   "+spec.sourceType);
                      System.out.println("    by:     "+spec.compType);
                      System.out.println("    to:     "+spec.destType);
                    */

                    spec.uniqueID =
                        GraphicsPrimitive.makeUniqueID(primTypeID, src, cmp, dst);
                    prim = locate(spec);
                    if (prim != null) {
                        //System.out.println("<GPMgr> Found: " + prim + " in " + i + " steps");
                        return prim;
                    }
                }
            }
        }
        return null;
    }

    private static GraphicsPrimitive locateGeneral(int primTypeID) {
        if (generalPrimitives == null) {
            return null;
        }
        for (int i = 0; i < generalPrimitives.length; i++) {
            GraphicsPrimitive prim = generalPrimitives[i];
            if (prim.getPrimTypeID() == primTypeID) {
                return prim;
            }
        }
        return null;
        //throw new InternalError("No general handler registered for"+signature);
    }

    private static GraphicsPrimitive locate(PrimitiveSpec spec) {
        if (needssort) {
            if (GraphicsPrimitive.traceflags != 0) {
                for (int i = 0; i < primitives.length; i++) {
                    primitives[i] = primitives[i].traceWrap();
                }
            }
            Arrays.sort(primitives, primSorter);
            needssort = false;
        }
        GraphicsPrimitive[] devCollection = primitives;
        if (devCollection == null) {
            return null;
        }
        int index = Arrays.binarySearch(devCollection, spec, primFinder);
        if (index >= 0) {
            GraphicsPrimitive prim = devCollection[index];
            if (prim instanceof GraphicsPrimitiveProxy) {
                prim = ((GraphicsPrimitiveProxy) prim).instantiate();
                devCollection[index] = prim;
                if (debugTrace) {
                    writeLog("Instantiated graphics primitive " + prim);
                }
            }
            if (debugTrace) {
                writeLog("Lookup found[" + index + "]["+ prim + "]");
            }
            return prim;
        }
        if (debugTrace) {
            writeLog("Lookup found nothing for:");
            writeLog(" " + spec.uniqueID);
        }
        return null;
    }

    private static void writeLog(String str) {
        if (debugTrace) {
            System.err.println(str);
        }
    }

    /**
     * Test that all of the GraphicsPrimitiveProxy objects actually
     * resolve to something.  Throws a RuntimeException if anything
     * is wrong, an has no effect if all is well.
     */
    // This is only really meant to be called from GraphicsPrimitiveProxyTest
    // in the regression tests directory, but it has to be here because
    // it needs access to a private data structure.  It is not very
    // big, though.
    public static void testPrimitiveInstantiation() {
        testPrimitiveInstantiation(false);
    }

    public static void testPrimitiveInstantiation(boolean verbose) {
        int resolved = 0;
        int unresolved = 0;
        GraphicsPrimitive[] prims = primitives;
        for (int j = 0; j < prims.length; j++) {
            GraphicsPrimitive p = prims[j];
            if (p instanceof GraphicsPrimitiveProxy) {
                GraphicsPrimitive r = ((GraphicsPrimitiveProxy) p).instantiate();
                if (!r.getSignature().equals(p.getSignature()) ||
                    r.getUniqueID() != p.getUniqueID()) {
                    System.out.println("r.getSignature == "+r.getSignature());
                    System.out.println("r.getUniqueID == " + r.getUniqueID());
                    System.out.println("p.getSignature == "+p.getSignature());
                    System.out.println("p.getUniqueID == " + p.getUniqueID());
                    throw new RuntimeException("Primitive " + p
                                               + " returns wrong signature for "
                                               + r.getClass());
                }
                // instantiate checks that p.satisfiesSameAs(r)
                unresolved++;
                p = r;
                if (verbose) {
                    System.out.println(p);
                }
            } else {
                if (verbose) {
                    System.out.println(p + " (not proxied).");
                }
                resolved++;
            }
        }
        System.out.println(resolved+
                           " graphics primitives were not proxied.");
        System.out.println(unresolved+
                           " proxied graphics primitives resolved correctly.");
        System.out.println(resolved+unresolved+
                           " total graphics primitives");
    }

    public static void main(String argv[]) {
        // REMIND: Should trigger loading of platform primitives somehow...
        if (needssort) {
            Arrays.sort(primitives, primSorter);
            needssort = false;
        }
        testPrimitiveInstantiation(argv.length > 0);
    }
}
