/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms.
 *
 * This file is available and licensed under the following license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *   * Neither the name of Sun Microsystems nor the names of its contributors
 *     may be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package lazyloader;

import java.awt.AWTEvent;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.HierarchyEvent;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import javafx.async.RunnableFuture;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 *
 @author Rakesh Menon
 */ 
public class LazyClassLoader implements RunnableFuture, AWTEventListener {
    
    private String className;
    private List urls;
    private CallbackHandler cbh = null;
    private JFrame frame = null;
    
    public LazyClassLoader(CallbackHandler cbh) {

        this.cbh = cbh;
        
        this.className = cbh.getClassName();
        this.urls = cbh.getURLList();

        Toolkit.getDefaultToolkit().addAWTEventListener(
            this, AWTEvent.HIERARCHY_EVENT_MASK );
    }
    
    public void run() {
        
        try {
            
            List<URL> urlList = new ArrayList<URL>();
            for(Object url : urls) {
                urlList.add(new URL(url.toString()));
            }

            /**
             * Set ClassLoader
             */
            URLClassLoader urlClassLoader = new URLClassLoader(
                    (URL[])urlList.toArray(new URL[] { }), getClass().getClassLoader());
            Thread.currentThread().setContextClassLoader(urlClassLoader);

            /**
             * * Launch JavaFX Application
             */
            Class mainClazz = Class.forName(
                "com.sun.javafx.runtime.Main", true, urlClassLoader);
            Method mainMethod = mainClazz.getMethod("main", String[].class);
            String[] args = new String[] { "MainJavaFXScript=" + className };
            mainMethod.invoke(null, new Object[] { args });
            
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void eventDispatched(AWTEvent event) {

        // Ignore events from main Frame
        if(!(event.getSource() instanceof JFrame)) {
            return;
        else if("Lazy-Loader".equals(((JFrame)event.getSource()).getTitle())) {
            return;
        }
        
        if(event.getID() == HierarchyEvent.HIERARCHY_CHANGED) {

            HierarchyEvent he = (HierarchyEventevent;

            if(he.getChangeFlags() == HierarchyEvent.DISPLAYABILITY_CHANGED) {

                    if(frame != null) { return}                    
                    frame = (JFrameevent.getSource();

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            JComponent appContainer = (JComponentframe.getContentPane();
                            frame.remove(appContainer);
                            cbh.onLaunch(appContainer);
                        }
                    });

            else if(he.getChangeFlags() == HierarchyEvent.SHOWING_CHANGED) {
                Toolkit.getDefaultToolkit().removeAWTEventListener(this);
                frame.dispose();
            }
        }
    }
}