/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 */
package org.apache.avalon.phoenix.frontends;

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.io.File;
import java.lang.Thread;
import java.lang.Runnable;
import java.net.URL;

import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.avalon.framework.ExceptionUtil;
import org.apache.avalon.framework.logger.AvalonFormatter;
import org.apache.avalon.framework.logger.LogKitLogger;
import org.apache.avalon.framework.logger.Logger;
import org.apache.avalon.framework.parameters.Parameterizable;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.excalibur.i18n.ResourceManager;
import org.apache.avalon.excalibur.i18n.Resources;
import org.apache.avalon.phoenix.components.embeddor.URLSingleAppEmbeddor;
import org.apache.avalon.phoenix.interfaces.Embeddor;
import org.apache.log.Hierarchy;
import org.apache.log.LogTarget;
import org.apache.log.Priority;
import org.apache.log.output.io.FileTarget;
/**
 * Applet frontends for URLSingleAppEmbeddor.
 *
 * @author <a href="mailto:james.lau@3pro.com.hk">James Lau</a>
 * @version CVS $Revision:$ $Date:$
*/

public class PhoenixApplet extends Applet implements Runnable {
    boolean isStandalone = false;

    private static final Resources REZ =
        ResourceManager.getPackageResources( PhoenixApplet.class );

    private static final String DEFAULT_LOG_FILE = "/.phoenix/logs/phoenix.log";

    private final static String DEFAULT_FORMAT =
        "%{time} [%7.7{priority}] (%{category}): %{message}\\n%{throwable}";

    private String phoenixHome;

    private Parameters m_parameters;
    private URLSingleAppEmbeddor m_embeddor;

  //Get a parameter value
  public String getParameter(String key, String def) {
    return isStandalone ? System.getProperty(key, def) :
      (getParameter(key) != null ? getParameter(key) : def);
  }

  //Construct the applet
  public PhoenixApplet() {
  }
  //Initialize the applet
  public void init() {
    String logDestination = "";
    String logPriority = "";
    String appName = "";
    String appLoc = "";

    try {
      logDestination =
            this.getParameter( "log-destination",
                System.getProperty("user.home") + DEFAULT_LOG_FILE );
      logPriority = this.getParameter( "log-priority", "INFO" );
      appName = this.getParameter( "application-name", "default" );

      if (isStandalone) {
        File file = new File(this.getParameter("phoenix.home", "./")).getCanonicalFile();
        phoenixHome = file.toURL().toString();
      } else {
         phoenixHome = getCodeBase().toString();
      }
      appLoc = this.getParameter(
          "application-location", phoenixHome + "apps/") + appName + ".sar";
      //System.out.println("phoenix.home:"+phoenixHome);
      //System.out.println("application-location:"+appLoc);
    }
    catch(Exception e) {
      e.printStackTrace();
    }

    //TODO: configuring with more parameters.

    m_parameters = new Parameters();
    m_parameters.setParameter( "log-destination", logDestination );
    m_parameters.setParameter( "log-priority", logPriority );
    m_parameters.setParameter( "application-name", appName );
    m_parameters.setParameter( "application-location", appLoc );

    try
    {
      m_embeddor = new URLSingleAppEmbeddor();
      m_embeddor.enableLogging( createLogger( m_parameters ) );
      if ( m_embeddor instanceof Parameterizable )
      {
        ( (Parameterizable)m_embeddor ).parameterize( m_parameters );
      }
      m_embeddor.initialize();

      Thread thread = new Thread( this, "Phoenix" );
      thread.start();

      }
      catch ( final Throwable throwable )
      {
        System.out.println(REZ.getString( "main.exception.header" ) );
        System.out.println( "---------------------------------------------------------" );
        System.out.println( ExceptionUtil.printStackTrace( throwable ) );
        System.out.println( "---------------------------------------------------------" );
        System.out.println( REZ.getString( "main.exception.footer" ) );
      }
  }

  //Destroy the applet
  public void destroy() {
    try
    {
      m_embeddor.dispose();
      m_embeddor = null;
      m_parameters = null;
    }
    catch ( final Throwable throwable )
    {
      System.out.println( REZ.getString( "main.exception.header" ) );
      System.out.println( "---------------------------------------------------------" );
      System.out.println( ExceptionUtil.printStackTrace( throwable ) );
      System.out.println( "---------------------------------------------------------" );
      System.out.println( REZ.getString( "main.exception.footer" ) );
    }
  }
  //Get Applet information
  public String getAppletInfo() {
    return "Phoenix Applet";
  }
  //Get parameter info
  public String[][] getParameterInfo() {
    String[][] pinfo =
      {
      {"log-destination", "String", System.getProperty("user.home") + DEFAULT_LOG_FILE},
      {"log-priority", "String", "INFO"},
      {"application-name", "String", "default"},
      {"application-location", "String", getCodeBase() + "/apps/{application-name}.sar"},
      };
    return pinfo;
  }

  public void run()
  {
    try
    {
      m_embeddor.execute();
    }
    catch ( final Throwable throwable )
    {
      System.out.println( REZ.getString( "main.exception.header" ) );
      System.out.println( "---------------------------------------------------------" );
      System.out.println( ExceptionUtil.printStackTrace( throwable ) );
      System.out.println( "---------------------------------------------------------" );
      System.out.println( REZ.getString( "main.exception.footer" ) );

      final String message = REZ.getString( "applet.error.execute" );
      throw new CascadingRuntimeException( message, throwable );
    }
  }

  private Logger createLogger( final Parameters parameters )
        throws Exception
  {
      final String userHome = parameters.getParameter(
          "user.home", System.getProperty("user.home"));
      final String logDestination =
            parameters.getParameter( "log-destination", userHome + DEFAULT_LOG_FILE );
      final String logPriority =
            parameters.getParameter( "log-priority", "INFO" );
      final AvalonFormatter formatter = new AvalonFormatter( DEFAULT_FORMAT );
      final File file = new File( logDestination );
      final FileTarget logTarget = new FileTarget( file, false, formatter );

      //Create an anonymous hierarchy so no other
      //components can get access to logging hierarchy
      final Hierarchy hierarchy = new Hierarchy();
      final org.apache.log.Logger logger = hierarchy.getLoggerFor( "Phoenix" );
      logger.setLogTargets( new LogTarget[]{logTarget} );
      logger.setPriority( Priority.getPriorityForName( logPriority ) );
      logger.info( "Logger started" );
      return new LogKitLogger( logger );
  }

  //Main method
  public static void main(String[] args) {
    PhoenixApplet applet = new PhoenixApplet();
    applet.isStandalone = true;
    Frame frame;
    frame = new Frame() {
      protected void processWindowEvent(WindowEvent e) {
        super.processWindowEvent(e);
        if (e.getID() == WindowEvent.WINDOW_CLOSING) {
          System.exit(0);
        }
      }
      public synchronized void setTitle(String title) {
        super.setTitle(title);
        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
      }
    };
    frame.setTitle("Phoenix Applet");
    frame.add(applet, BorderLayout.CENTER);
    applet.init();
    applet.start();
    frame.setSize(400,320);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    frame.setLocation((d.width - frame.getSize().width) / 2, (d.height - frame.getSize().height) / 2);
    //frame.setVisible(true);
  }
}