/**
 * Title:
 * @version:    $Id: AdminController.java,v 1.2 2005/08/05 16:49:10 rob Exp $
 * Copyright:   Copyright (C) 2003 Ian Ibbotson
 * @author:     Ian Ibbotson
 * Company:
 * Description:
 */

package com.k_int.AdminApp.gui.ExplorerView;

import java.awt.Component;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Locale;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.MissingResourceException;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import com.k_int.AdminApp.config.*;
import com.k_int.AdminApp.gui.AdminControllerComponent;
import com.k_int.AdminApp.gui.ControllerOwner;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;




import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.*;







public class AdminController implements ActionListener, ControllerOwner {

  public static Log log = LogFactory.getLog(AdminController.class);
  private static ApplicationContext ctx = null;

  private Hashtable active_components = new Hashtable();
  private static ResourceBundle resources;

  private ActionCategory root_category;
  private ConfigHolder config;

  private CloseableTabbedPane tab_pane;

  private JFrame view = null;

  private JLabel status_text = new JLabel("Not logged in",SwingConstants.RIGHT);

  static {
    try {
      resources = ResourceBundle.getBundle("XDAdmin", Locale.getDefault());
    }
    catch (MissingResourceException e) {
      log.error("XDAdmin.properties not found",e);
      System.exit(1);
    }
  }

  public static ResourceBundle getResources() {
    return resources;
  }

  public AdminController(String config_context) {
    tab_pane = new CloseableTabbedPane(this);

    try {
      if ( config_context != null )
        ctx = new ClassPathXmlApplicationContext( new String[] { config_context } );
      else
        ctx = new StaticApplicationConext();
    }
    catch ( Exception e ) {
      log.warn("Problem",e);
    }

    // Databases and applications a user has access to has nothing to do with what is presented in their
    // UI (Sorta)

    // Get connection to core application database

    // Things need to be installed into spring context

    // Install Explorer Application Instance

    // Install Data upload tool instance

    createView();
  }

  public void createView() {
    view = new JFrame();
    view.getContentPane().setLayout(new BorderLayout());

    view.setTitle(resources.getString("AppName"));
    view.setBounds(50, 50, 850, 650);
    view.getContentPane().add(tab_pane, BorderLayout.CENTER);
    view.getContentPane().add(status_text, BorderLayout.SOUTH);

    initializeMenu();
  }

  public Component getView() {
    return view;
  }

  public Object getComponentId() {
    return new Long(this.hashCode());
  }


  public void addComponent(AdminControllerComponent component) {
    log.debug("AdminController::Adding "+component);
    active_components.put(component.getComponentId(), component);
    tab_pane.addTab(component.getName(),component.getView(), component.isCloseable());
  }

  public void addMenu(JMenu menu)
  {
    view.getJMenuBar().add(menu);
  }

  private void initializeMenu()
  {
    view.setJMenuBar(new JMenuBar());
    initializeFileMenu();
    

    // Now we need to walk through the root category adding menus and actions for
    // the categories and actions we find there.
    /*
    com.k_int.AdminApp.config.ActionCategory root_cat = config.getRootCategory();

    for ( Enumeration e = root_cat.enumerateChildren(); e.hasMoreElements(); )
    {
      recurseCategory((ActionComponent)e.nextElement(), view.getJMenuBar());
    }

    for ( Enumeration e = config.getDefaultWorkspaceComponents().elements(); e.hasMoreElements(); )
    {
      ActionComponent ac = (ActionComponent)e.nextElement();
    }
    */
  }

  private void recurseCategory(ActionComponent component, Container parent)
  {
    if ( component instanceof com.k_int.AdminApp.config.ActionCategory )
    {
      ActionCategory action_cat = (ActionCategory)component;

      JMenu new_menu = new JMenu(action_cat.getText());
      
      
      parent.add(new_menu);
    }
    else
    {
      JMenuItem new_menu_item = new JMenuItem(createAction(component));
      parent.add(new_menu_item);
    }

  }

  private void initializeFileMenu()
  {
    JMenu fileMenu = new JMenu(resources.getString("File"));

    // fileMenu.addSeparator();

    JMenuItem jmiExit = new JMenuItem(resources.getString("Exit"));
    jmiExit.addActionListener(this);
    fileMenu.add(jmiExit);

    view.getJMenuBar().add(fileMenu);
  }


  public static final ImageIcon getImage(String type, String filename)
  {
    URL url = ClassLoader.getSystemResource("com/k_int/AdminApp/gui/icons/"+type+"/" + filename);

    if (url != null)
      return new ImageIcon(url);
    else
      return null;
  }

  public void actionPerformed(ActionEvent e)
  {
    String a = e.getActionCommand();

    if (e.getSource() instanceof JMenuItem) {
      if (a.equals(resources.getString("Exit"))) {
        log.debug("GC before exit....");
        System.gc();
        log.debug("Exiting....");
        System.exit(0);
      }
    }
  }

  public void componentCloseNotification(AdminControllerComponent component)
  {
    log.debug("Component "+component.getName()+" closing.. remove from hashtable");
    // Get the controller component
    AdminControllerComponent c = (AdminControllerComponent)active_components.remove(component.getComponentId());
    
    log.debug("Got component "+c+" remove from tab_pane");

    // Look up and remove the view
    tab_pane.remove(c.getView());
  }

  // The hard-coded ness sucks.. But.. In order for the action definition to be reusable in a
  // web app, we don't want to create an abstract getAction method on the ActionComponent,
  // Since it would then have to know about struts and lots of other stuff. The Description
  // must remain a neutral object that just describes some action. We might however provide
  // a swing specific mapping that tells this method what factory to use later on. Maybe we
  // can configure that from a props file in the jar.
  public AbstractAction createAction(ActionComponent component)
  {
    AbstractAction result = null;
    log.debug("AdminController:: createAction");
    return result;
  }

  // Execute the action specified
  public void createWorkspaceComponent(ActionComponent ac)
  {
    log.debug("createWorkspaceComponent");
    AbstractAction aa = createAction(ac);
    aa.actionPerformed(new ActionEvent(this,0,"WorkspaceCreate"));
  }
}
