/*
** 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.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import org.jdom.*;
import org.jdom.input.*;
import luxor.spi.*;
import luxor.status.*;
import luxor.swing.*;
import luxor.*;

public class XulFormHelper implements JComponentResolver
{

   static Logger T = Logger.getLogger( XulFormHelper.class );

   private NContainer _container;
   private String _formKey;

   private LinkedHashMap _inputIndex = new LinkedHashMap( 13 );

   private HashMap _jcomponentIndex = new HashMap( 13 );

   public XulFormHelper( String formKey )
   {
      _formKey = formKey;
   }

   public void setup()
   {
      T.debug( "enter setup()" );

      XulManager xul = XulManager.getXulManager();

      _container = xul.createNContainerFromBox( _formKey, this );

      if( _container == null )
      {
         Xul.error( "form '" + _formKey + "' not found; cannot setup form" );
         return;
      }

      // link and resolve input controls
      linkControls();
   }

   public Iterator getInputControls()
   {
      return _inputIndex.values().iterator();
   }

   public JComponent getJComponent()
   {
      if( _container == null )
         return null;
      else
         return _container.getJComponent();
   }

   public List getValidationErrors()
   {
      ArrayList errors = new ArrayList();

      for( Iterator it = _inputIndex.entrySet().iterator(); it.hasNext();  )
      {
         Map.Entry entry = ( Map.Entry ) it.next();

         String key = ( String ) entry.getKey();
         XulInput input = ( XulInput ) entry.getValue();

         errors.addAll( input.getValidator().getErrors() );
      }

      return errors;
   }


   public boolean isValid()
   {
      // loop over input controls (xinput)

      boolean isValid = true;

      for( Iterator it = _inputIndex.entrySet().iterator(); it.hasNext();  )
      {
         Map.Entry entry = ( Map.Entry ) it.next();

         String key = ( String ) entry.getKey();
         XulInput input = ( XulInput ) entry.getValue();

         if( !input.isValid() )
            return false;
      }

      return isValid;
   }

   public void addComponent( String key, JComponent comp )
   {
      _jcomponentIndex.put( key, comp );
   }

   public void addInput( XulInput input )
   {
      _inputIndex.put( input.getId(), input );
   }

   /**
    *  export form's data as xml note: this method is currently experimental and
    *  will be changed and improved substantly over time
    */

   public String exportAsXml()
   {
      StringBuffer buf = new StringBuffer();

      buf.append( "<" + _formKey + ">\n" );
      for( Iterator it = _inputIndex.entrySet().iterator(); it.hasNext();  )
      {
         Map.Entry entry = ( Map.Entry ) it.next();

         String key = ( String ) entry.getKey();
         XulInput input = ( XulInput ) entry.getValue();

         buf.append( "<" + key + ">" + input.getText() + "</" + key + ">\n" );
      }
      buf.append( "</" + _formKey + ">\n" );

      return buf.toString();
   }

   /**
    *  import form's data from xml note: this method is currently experimental
    *  and will be changed and improved substantly over time
    */

   public void importFromXml( String xml )
   {
      try
      {
         Status.info( "auto-fill form " + _formKey + " using xml data" );

         SAXBuilder builder = new SAXBuilder();
         Document doc = builder.build( new StringReader( xml ) );

         // for now assume that root element holds all field data
         Element root = doc.getRootElement();

         // loop over root's element children and see if the match with an input control
         Iterator it = root.getChildren().iterator();
         while( it.hasNext() )
         {
            // todo: use instanceof to check if child is an element
            Element inputData = ( Element ) it.next();

            String name = inputData.getName();
            XulInput input = ( XulInput ) _inputIndex.get( name );
            if( input == null )
            {
               Status.info( "  field " + name + " not found; data ignored" );
            }
            else
            {
               String value = inputData.getTextTrim();
               Status.info( "  setting field " + name + " to " + value );
               input.setText( value );
            }
         }
      }
      catch( JDOMException jex )
      {
         Xul.error( "failed to parse form data: " + jex.toString() );
      }
   }

   public void linkControls()
   {
      T.debug( "enter linkControls()" );

      // link input controls (XulInput) with components

      for( Iterator it = _inputIndex.entrySet().iterator(); it.hasNext();  )
      {
         Map.Entry entry = ( Map.Entry ) it.next();

         String key = ( String ) entry.getKey();
         XulInput input = ( XulInput ) entry.getValue();

         T.debug( "link control " + key );

         NInput comp = _container.lookupNInput( key );
         if( comp == null )
         {
            Xul.error( "failed to resolve input reference " + key + "; input reference not found" );
            continue;
         }
         input.setComponent( comp );
      }

      T.debug( "leave linkControls()" );
   }

   public JComponent lookupJComponent( String key )
   {
      return ( JComponent ) _jcomponentIndex.get( key );
   }

}