/*
** Luxor - XML User Interface Language (XUL) Toolkit
** Copyright (c) 2001, 2002 by Gerald Bauer
**
** This program is free software.
**
** You may redistribute it and/or modify it under the terms of the GNU
** General Public License as published by the Free Software Foundation.
** Version 2 of the license should be included with this distribution in
** the file LICENSE, as well as License.html. If the license is not
** included with this distribution, you may find a copy at the FSF web
** site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
** Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/

package luxor.core;

import java.io.*;
import java.util.*;
import org.jdom.*;
import org.jdom.input.*;
import luxor.core.box.*;
import luxor.core.data.*;
import luxor.core.grid.*;
import luxor.core.input.*;
import luxor.core.menu.*;
import luxor.core.misc.*;
import luxor.core.portal.*;
import luxor.core.tab.*;
import luxor.core.table.*;
import luxor.core.toolbar.*;
import luxor.core.widget.*;
import luxor.core.xslt.*;
import luxor.status.*;
import luxor.*;

public class XulLoader
{
   static Logger T = Logger.getLogger( XulLoader.class );

   private XulManager _manager;

   public XulLoader( XulManager manager )
   {
      _manager = manager;
   }

   public void load( String name )
   {
      try
      {
         T.debug( "loading xul file " + name );
         InputStream in = _manager.getResourceAsStream( name );

         SAXBuilder builder = new SAXBuilder();
         Document doc = builder.build( in );

         Element xul = doc.getRootElement();
         createElements( null, xul );
         T.debug( "xul file " + name + " successfully loaded" );
      }
      catch( JDOMException jex )
      {
         Xul.error( "failed to load xul file '" + name + "': " + jex.toString() );
      }
   }

   protected void createElements( XulContainer parent, Element element )
   {
      String type = element.getName();
      if( type.equals( Xul.Element.XUL ) )
      {
         parent = new XulDef( element, _manager );
      }
      else if( type.equals( Xul.Element.STYLESHEET ) )
      {
         StylesheetDef def = new StylesheetDef( element );

         Element result = def.getContent();

         List children = result.getChildren();
         if( children.size() == 0 )
            // no content; don't bother
            return;

         // swap content; use stylesheet transformed content
         // don't touch parent; so stylesheet/result stays "invisible"/is ignored

         // todo:
         //  1) do i need to unmount stylesheet
         //     and replace it with the transformed content/result?
         //  2) who is using parent?
         // --
         //  is this a quick and dirty hack?
         //  should i put the transformation of templates/stylesheets in it's own pass
         //   and keep it separate from the ui construction?
         element = result;
      }
      else if( type.equals( Xul.Element.DATAGRID ) )
      {
         DataGridDef def = new DataGridDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.COLGROUP ) )
      {
         ColGroupDef def = new ColGroupDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TREE ) )
      {
         TreeDef def = new TreeDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.GRID ) )
      {
         GridDef def = new GridDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.COLUMNS ) )
      {
         ColumnsDef def = new ColumnsDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.COLUMN ) )
      {
         ColumnDef def = new ColumnDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.ROWS ) )
      {
         RowsDef def = new RowsDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.ROW ) )
      {
         RowDef def = new RowDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TABBOX ) )
      {
         TabBoxDef def = new TabBoxDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TABS ) )
      {
         TabsDef def = new TabsDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TABPANELS ) )
      {
         TabPanelsDef def = new TabPanelsDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TABPANEL ) )
      {
         TabPanelDef def = new TabPanelDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.BOX ) )
      {
         BoxDef def = new BoxDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.HBOX ) )
      {
         HBoxDef def = new HBoxDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.VBOX ) )
      {
         VBoxDef def = new VBoxDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.GROUPBOX ) )
      {
         GroupBoxDef def = new GroupBoxDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.ANIM ) )
      {
         AnimDef def = new AnimDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TOOLBAR ) )
      {
         ToolBarDef def = new ToolBarDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.KEYSET ) )
      {
         KeySetDef def = new KeySetDef( element, _manager );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.MENUBAR ) )
      {
         MenuBarDef def = new MenuBarDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.MENU ) )
      {
         MenuDef def = new MenuDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.MENUPOPUP ) )
      {
         MenuPopupDef def = new MenuPopupDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.POPUP ) )
      {
         PopupDef def = new PopupDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.PORTAL ) )
      {
         PortalDef def = new PortalDef( element );
         parent.add( def );
         return;
         // note: we want to keep all content
         // attached verbatim to portal element
         // no further processing of children desired
      }
      else if( type.equals( Xul.Element.PORTLET ) )
      {
         PortletRef ref = new PortletRef( element );
         parent.add( ref );
         parent = ref;
      }
      else if( type.equals( Xul.Element.LIST ) )
      {
         ListDef def = new ListDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.MAP ) )
      {
         MapDef def = new MapDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TABLE ) )
      {
         TableDef def = new TableDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TR ) )
      {
         TableRowDef def = new TableRowDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.TD ) )
      {
         TableDataDef def = new TableDataDef( element );
         parent.add( def );
         parent = def;
      }
      else if( type.equals( Xul.Element.MENUITEM ) )
      {
         MenuItemDef def = new MenuItemDef( element );
         parent.add( def );
         // menuitem shouldn't contain any elements
      }
      else if( type.equals( Xul.Element.MENUREF ) )
      {
         MenuRef ref = new MenuRef( element );
         parent.add( ref );
      }
      else if( type.equals( Xul.Element.KEY ) )
      {
         KeyDef def = new KeyDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.BUTTON ) )
      {
         ButtonDef def = new ButtonDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.TOOLBARBUTTON ) )
      {
         ToolBarButtonDef def = new ToolBarButtonDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.TOOLBARSEPARATOR ) )
      {
         ToolBarSeparatorDef def = new ToolBarSeparatorDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.SEPARATOR ) )
      {
         SeparatorDef def = new SeparatorDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.MENUSEPARATOR ) )
      {
         MenuSeparatorDef def = new MenuSeparatorDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.ICON ) )
      {
         IconDef def = new IconDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.COMPONENTREF )
             || type.equals( Xul.Element.GADGET ) )
      {
         ComponentRef ref = new ComponentRef( element );
         parent.add( ref );
      }
      else if( type.equals( Xul.Element.LABEL ) )
      {
         LabelDef def = new LabelDef( element );
         parent.add( def );
         return;
         // note: we want to keep all content
         // attached verbatim to portal element
         // no further processing of children desired
      }
      else if( type.equals( Xul.Element.CHOICE ) )
      {
         ChoiceDef def = new ChoiceDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.MCHOICE ) )
      {
         MChoiceDef def = new MChoiceDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.CHECKBOX ) )
      {
         CheckBoxDef def = new CheckBoxDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.TEXTAREA ) )
      {
         TextAreaDef def = new TextAreaDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.TEXT ) )
      {
         TextDef def = new TextDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.PASSWORD ) )
      {
         PasswordDef def = new PasswordDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.DISPLAYURL ) )
      {
         DisplayUrlDef def = new DisplayUrlDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.ENTRY ) )
      {
         ListEntryDef def = new ListEntryDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.COMMAND ) )
      {
         CommandDef def = new CommandDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.SPACER ) )
      {
         SpacerDef def = new SpacerDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.TAB ) )
      {
         TabDef def = new TabDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.CAPTION ) )
      {
         CaptionDef def = new CaptionDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.IFRAME ) )
      {
         IFrameDef def = new IFrameDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.IMAGE ) )
      {
         ImageDef def = new ImageDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.COL ) )
      {
         ColDef def = new ColDef( element );
         parent.add( def );
      }
      else if( type.equals( Xul.Element.PRE ) )
      {
         PreDef def = new PreDef( element );
         parent.add( def );
      }
      else
      {
         Xul.syntax( "unsupported element '" + type + "'" );
      }

      // process children
      List list = element.getChildren();
      for( Iterator it = list.iterator(); it.hasNext();  )
      {
         Element child = ( Element ) it.next();
         createElements( parent, child );
      }
   }
}