/**
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * 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 org.jboss.webbeans.environment.se;

import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.webbeans.CurrentManager;
import org.jboss.webbeans.context.ApplicationContext;
import org.jboss.webbeans.context.DependentContext;
import org.jboss.webbeans.context.beanmap.SimpleBeanMap;
import org.jboss.webbeans.environment.se.beans.ParametersFactory;
import org.jboss.webbeans.environment.se.bootstrap.WebBeansBootstrap;
import org.jboss.webbeans.environment.se.events.Setup;
import org.jboss.webbeans.environment.se.events.Start;
import org.jboss.webbeans.environment.se.exception.CleanShutdownException;

import java.awt.HeadlessException;

import javax.inject.manager.Manager;
import org.jboss.webbeans.environment.se.events.Shutdown;

/**
 * This is the main class that should always be called from the command
 * line for a plebeians app. Something like:
 * <code>
 * java -jar MyApp.jar org.jboss.webbeans.environment.se.StarMain arguments
 * </code>
 * @author Peter Royle
 */
public class StartMain
{

    String[] args;

    public StartMain( String[] commandLineArgs )
            throws HeadlessException
    {
        this.args = commandLineArgs;
    }

    public void go()
    {
        WebBeansBootstrap webBeansBootstrap = new WebBeansBootstrap();
        webBeansBootstrap.boot();

        Manager manager = webBeansBootstrap.getManager();

        // init the bean map for the dependent and application context
        ApplicationContext.INSTANCE.setBeanMap( new SimpleBeanMap() );
        manager.addContext( DependentContext.INSTANCE );
        manager.addContext( ApplicationContext.INSTANCE );

        // TODO: I have no idea if this is OK??? The WB spec says that the 
        // dependant scoe is only active when the manager is doing its work.
        // This leaves it open for the whole duration. I guess that's about
        // right since the main bean is in the dependant scope?
        DependentContext.INSTANCE.setActive( true );

        try
        {
            ParametersFactory paramsFactory =
                    (ParametersFactory) CurrentManager.rootManager().getInstanceByType( ParametersFactory.class );
            paramsFactory.setArgs( this.args );
        } finally
        {
            // clean up and shut down
            DependentContext.INSTANCE.setActive( false );
        }

        try
        {
            // The main application can take this opportunity to perform
            // additional set up steps, such as initialising custom contexts.
            CurrentManager.rootManager().fireEvent( new Setup() );

            // The main method should be an observer of this event so it gets
            // called automatically by the WebBean manager.
            CurrentManager.rootManager().fireEvent( new Start() );
        } catch (Throwable e)
        {
            handleException( e );
        }
//        try
//        {
//            Thread.sleep( Long.MAX_VALUE );
//        } catch (InterruptedException ex)
//        {
//            System.out.println("asdfsfsdafdsfasdfsfdf");
//        }

        // Give apps and modules chance to shutdown cleanly
        CurrentManager.rootManager().fireEvent( new Shutdown() );

    }

    /**
     * The main method called from the command line. This little puppy
     * will get the ball rolling.
     * @param args the command line arguments
     */
    public static void main( String[] args )
    {
        new StartMain( args ).go();
    }

    /**
     * When an exception happens in your main app, you don't want
     * the manager to come down in a screaming heap. Well, not all the time.
     * Sometimes you just want to exit gently. This method will detect such
     * times and behave appropriately.
     * @param e
     */
    private void handleException( Throwable e )
    {
        // check for a 'special' root cause
        boolean dealtWith = false;
        Throwable cause = e.getCause();

        while (cause != null)
        {
            if (cause instanceof CleanShutdownException)
            {
                // This is a request to shut down silently, so swollow it.
                // Hoewver, if there's a message, then print it to stdout
                if (cause.getMessage() != null)
                {
                    System.out.println( cause.getMessage() );
                }

                dealtWith = true;
            }

            cause = cause.getCause();
        }

        if (!dealtWith)
        {
            e.printStackTrace();
        }
    }
}
