package JEM.Utils;
/**
 * ReadGuiPropertyList
 *
 * Used to setup properties for widgets.
 *
 * @author  Jere McDevitt
 *
 */
   
import java.lang.*;
import java.io.*;
import java.awt.Color;
import java.awt.Font;
import marimba.persist.*;
import marimba.io.*;
import marimba.gui.*;
import java.util.*;

class ReadGuiListEntry
{
    final public static int typeObject = 0;
    final public static int typeBoolean = 1;
    final public static int typeInt = 2;
    final public static int typeLong = 3;
    final public static int typeString = 4;
    final public static int typeColor = 5;
    final public static int typeFont = 6;
    final public static int typeByteArray = 7;
    final public static int typeObjectArray = 8;
    final public static int typeOption = 9;
    
    Object theData;
    public int  theOptionNumber = -1;
    public String theOtherString = null;
    public int  theDataType = typeObject;
    
    public String getTypeString()
    {
        String theTypes[] =
        {
            "Object",
            "boolean",
            "int",
            "long",
            "String",
            "Color",
            "Font",
            "byte[]",
            "Object[]",
            "Option"
        };
        return theTypes[theDataType];
    }

    public ReadGuiListEntry(marimba.persist.Options option, int i, String other)
    {
        theOptionNumber = i;
        theData = option;
        theDataType = typeOption;
        theOtherString = other;
    }
    
    public ReadGuiListEntry( Object obj )
    {
        theData = obj;
        theDataType = typeObject;
    }
    public ReadGuiListEntry( boolean bool )
    {
        theData = new Boolean( bool );
        theDataType = typeBoolean;
    }
    public ReadGuiListEntry( int val )
    {
        theData = new Integer(val);
        theDataType = typeInt;
    }
    public ReadGuiListEntry( long val )
    {
        theData = new Long(val);
        theDataType = typeLong;
    }   
    
    public ReadGuiListEntry( String val, String other )
    {
        theData = val;
        theDataType = typeString;
        theOtherString = other;
    }
    public ReadGuiListEntry( Color color)
    {
        theData = color;
        theDataType = typeColor;
    }   
    public ReadGuiListEntry( Font font)
    {
        theData = font;
        theDataType = typeFont;
    }   
    public ReadGuiListEntry( byte[] ab)
    {
        theData = ab;
        theDataType = typeByteArray;
    }   
    
    public ReadGuiListEntry( Object[] ob)
    {
        theData = ob;
        theDataType = typeObjectArray;
    }   
    
    public boolean booleanValue()
    {
        if( theDataType != typeBoolean )
          return false;
        return ((Boolean)theData).booleanValue();
    }
    public int intValue()
    {
        if( theDataType != typeInt && theDataType != typeLong )
          return -1;
        return ((Integer)theData).intValue();
    }
    public long longValue()
    {
        if( theDataType != typeLong && theDataType != typeInt )
          return -1;
        return ((Long)theData).longValue();
    }
    public String stringValue()
    {
        if( theDataType != typeString )
          return null;
        return (String)theData;
    }
    public Color colorValue()
    {
        if( theDataType != typeColor )
          return null;
        return (Color)theData;
    }
    
    public Font fontValue()
    {
        if( theDataType != typeFont )
          return null;
        return (Font)theData;
    }
    public Object objectValue()
    {
        if( theDataType != typeObject )
          return null;
        return (Object)theData;
    }
    
    public byte[] byteArrayValue()
    {
        if( theDataType != typeByteArray )
          return null;
        return (byte[])theData;
    }
    public Object[] objectArrayValue()
    {
        if( theDataType != typeObjectArray )
          return null;
        return (Object[])theData;
    }
    
    public String optionValue()
    {
        if( theOtherString != null )
          return ((Options)theData).get(theOptionNumber);
        return null;
    }
    
}

public class ReadGuiPropertyList extends marimba.persist.PropertyList
{
    Hashtable m_hProperties = new Hashtable();
    boolean debug = false;
    
    public ReadGuiPropertyList()
    {
        super();
    }
    public void clear()
    {
        m_hProperties.clear();
    }

    public void setDebug(boolean flag )
    {
        debug = flag;
    }
    
    String doColor(Color c)
    {
        if( c == null )
            return "null";
        return "new Color(" + c.getRed() + "," + c.getGreen() + "," + c.getBlue() + ")";
    }
    /**
     * Writes out a multiline text string as a series of
     * strings concatenated.  It makes certain that any
     * imbedded quotation marks are escaped.
     */
    String writeMultilineString(String tabIndent, String msg)
    {   
        StringBuffer buff = new StringBuffer();
        if( msg.indexOf('\n') == -1 )
        {
            StringTokenizer str = new StringTokenizer(msg,"\"", true);
			   buff.append("\"");
            while( str.hasMoreTokens() )
            {
                String theLine = str.nextToken();
                if( theLine.equals("\"") )   
                    buff.append("\\" + "\"" );
                else
                    buff.append( theLine );
            }
			   buff.append("\"");
        }
        else
        {
            StringTokenizer str = new StringTokenizer(msg,"\n\"",true);
        
            buff.append(tabIndent + "\"");
            while( str.hasMoreTokens() )
            {
                String theLine = str.nextToken();
                if( theLine.equals("\"") )
                    buff.append("\\" + "\"");
                else
                  if( theLine.equals("\n") )
                {
                    if( str.hasMoreTokens() )
                        buff.append("\"+\n"+tabIndent+"\"");
                    else
                        buff.append("\";n");
                }
                else
                    buff.append(theLine );

            }
            buff.append("\";");
         }
        return new String(buff);
        
    }

    String doString( String str, String tabIndent)
    {
        if( str == null )
          return "null";
        if( str.indexOf('\"') != -1 || str.indexOf('\n') != -1)
          return writeMultilineString(tabIndent,str);
        return "\"" + str + "\"";
    }
    
    String doFont(Font f)
    {
        if( f == null )
            return "null";
        return "new Font(" + doString(f.getName(),"") + "," +
                                      f.getStyle() + "," + 
                                      f.getSize() + ")";
          
    }   
    String doOptions(String option, String name, Widget w)
    {
        String className = w.getClass().getName();
        boolean isTextView = (className.indexOf("TextView") != -1 );
        if( option == null )
          return "null";
        if( option.equals("autoFocus") )
          return name + ".getFocusOptions()";       
        if( option.equals("colHeaders") )
          return name + ".getColHeadersOptions()";      
        if( option.equals("sortMode") )
          return name + ".getSortModeOptions()";        
        if( option.equals("direction") )
          return name + ".getDirectionOptions()";       
        if( option.equals("orientation") )
          return name + ".getOrientationOptions()";     
        if( option.equals("cursor") )
          return name + ".getCursorOptions()";
        if( option.equals("tabmode") )
          return name + ".getTabOptions()";
        if( option.equals("diagonal") )
          return name + ".getDiagonalOptions()";        
        
        if( option.equals("wrap") )
            if( isTextView )
                return "TextView.wrapOptions";
            else
                return name + ".getWrapOptions()";      
     
        
        if( option.equals("fillmode") )
          return name + ".getFillOptions()";
        if( option.equals("linemode") )
          return name + ".getLineOptions()";
        if( option.equals("align") )
            if( isTextView )
                return "TextView.alignOptions";
            else
                return name + ".getAlignOptions()";
        
        if( option.equals("mode") )
          return name + ".getModeOptions()";
        if( option.equals("style") )
            if( isTextView )
                return "TextView.styleOptions";
            else
                return name + ".getStyleOptions()";
        if( option.equals("horizontal") )
          return name + ".getHorzOptions()";        
        if( option.equals("vertical") )
          return name + ".getVertOptions()";        
        return "UNDEFINED";
    }
    

    String doSourceFunction(String srcFunc, String str )
    {
        String name = null;
        if( srcFunc == null )
          return doString(str,null);
        
        int index = str.lastIndexOf('/');
        if( index == -1 )
          index = str.lastIndexOf('\\');
        if( index == -1 )
          index = str.lastIndexOf('~');
        if( index != -1 )
          name = str.substring(index+1);
        
        index = srcFunc.indexOf('%');
        if( index == -1 )
        {
            if( srcFunc.indexOf('(') == -1 ) //not a function, just a path
              return doString(srcFunc + name, null);
            else
              return srcFunc + name;
        }
        String func = srcFunc.substring(0,index) +
                      name +
                      srcFunc.substring(index+1);
        return  func;
    }
    
    public void dumpProperties(FastOutputStream ps, String tabIndent, Hashtable m_theObjects, Widget w, String srcFunction)
    {
        String objName = (String)m_theObjects.get(w);
        
        if( objName == null )
          objName = "UNKNOWN";
        ps.println(tabIndent + "rgpl.clear();");
        for( Enumeration keys = m_hProperties.keys();keys.hasMoreElements();)
        {
            String key = (String)keys.nextElement();
            ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(key);
            if( object != null )
            {
                switch( object.theDataType )
                {
                case object.typeObject:
                        if( object.objectValue() != null )
                        {
                            Widget theObject = (Widget)object.objectValue();
                            if( theObject instanceof Widget )
                            {
                                Widget realWidget = theObject;
                                if( key.equalsIgnoreCase("layoutmgr") )
                                {
                                    String classname = realWidget.getClass().getName();
                                    while( !classname.endsWith("ListWidget") &&
                                           !classname.endsWith("TreeWidget") )
                                    {
                                        if( realWidget.getParent() != null )
                                        {
                                            realWidget = realWidget.getParent();
                                        }
                                        else
                                        {
                                            realWidget = theObject;
                                            break;
                                        }
                                        
                                    }
                                    
                                }
                                
                                String realWidgetName = (String)m_theObjects.get(realWidget);                           
                                if( realWidgetName == null )
                                  realWidgetName = objName;
                                ps.print(tabIndent + "rgpl.setObject(\"" + key + "\"," + realWidgetName + ",null);");
                            }
                            else
                            {
                                ps.println("//" + theObject.toString() );
                                ps.print(tabIndent + "rgpl.setObject(\"" + key + ",null,null);");
                            }
                            
                        }
                        break;
                case object.typeBoolean:
                        ps.print(tabIndent + "rgpl.setBoolean(\"" + key + "\"," +
                                      object.booleanValue() + ",false);");
                        break;
                case object.typeInt:
                            ps.print(tabIndent + "rgpl.setInteger(\"" + key + "\"," +
                                     object.intValue() + ",0);");
                        break;
                case object.typeLong:
                            ps.print(tabIndent + "rgpl.setLong(\"" + key + "\"," +
                                 object.longValue() + ",0);");                  
                        break;
                case object.typeString:
                        if( !key.equals("script") )
                        {
                            if( key.equals("src") || key.endsWith("sound") || key.equals("pattern"))
                            {
                                ps.print(tabIndent + "rgpl.setString(\""+key+"\"," + 
                                         doSourceFunction(srcFunction, object.stringValue()) + "," + 
                                         doString(object.theOtherString,tabIndent) + ");");
                            }
                            else
                            {
                                ps.print(tabIndent + "rgpl.setString(\"" + key + "\"," +
                                     doString(object.stringValue(),tabIndent) + "," + doString(object.theOtherString,tabIndent) + ");");                    
                            }
                            
                        }
                        else
                        {
                            ps.println(tabIndent + "/*") ;
                            ps.println(tabIndent + "scriptStr = " + 
                                       doString(object.stringValue(),tabIndent) + ";");
                            ps.println(tabIndent + "rgpl.setString(\"" + key + "\"," +
                                     "scriptStr,null);");
                            ps.print(tabIndent + "*/" );
                        }
                    
                        break;
                case object.typeColor:
                            ps.print(tabIndent + "rgpl.setColor(\"" + key + "\"," +
                                 doColor(object.colorValue()) + ",Color.black);");
                        break;
                case object.typeFont:
                            ps.print(tabIndent + "rgpl.setFont(\"" + key + "\"," +
                                     doFont(object.fontValue()) + ",null);");
                        break;                  
                case object.typeByteArray:
                        if( key.equals("clazz") )
                        {
                            ps.println("/* clazz defined ... not carried over */");
                        }
                        else
                        {
                            byte[] ab = object.byteArrayValue();
                            ps.println(tabIndent + "ba = new byte[" + ab.length + "];");
                            ps.println(tabIndent + "//only writes out non 0 bytes since new clears array");
                            for( int i = 0; i < ab.length; i++)
                            {
                                if( ab[i] != 0 )
                                    ps.println(tabIndent + "ba[" + i + "] = " + ab[i] + ";");
                            }
                            ps.print(tabIndent + "rgpl.setByteArray(\"" + key + "\",ba,null);");
                        }
                    
                        break;
                    case object.typeObjectArray:

                        if( !key.equals("widgets") )
                        {
                        
                            Object[] objects = object.objectArrayValue();
                            ps.println(tabIndent + "oa = new Object[" + objects.length + "];");
                            for( int i = 0; i < objects.length; i++)
                            {
                                ReadGuiPropertyList rgpl = new ReadGuiPropertyList();
                                if( objects[i] instanceof TableColumn)
                                {
                                    TableColumn tc = (TableColumn)objects[i];
                                    ps.print(tabIndent + "oa[" + i + "] = new TableColumn(");
                                    ps.println(doString(tc.label,tabIndent) + "," + tc.pos + "," + tc.size +"," + tc.displayIndex + ");");
                                    
                                }
                            }
                            ps.println(tabIndent + "rgpl.setObjectArray(\"" + key + "\"," + objects.length + ",oa);");
                            
                        }
                        break;
                case object.typeOption:
                            ps.print(tabIndent + "rgpl.setOption(\"" + key + "\"," + doOptions(key,objName, w) + "," +
                                     object.theOptionNumber + ",0);");
                        break;                  
                }
                
            }
        
            ps.print("\n");
        }
    }
    
    
    public void setBoolean(String string, boolean flag1, boolean flag2)
    {
        if( flag1 != flag2)
          m_hProperties.put(string,new ReadGuiListEntry(flag1) );
    }
    
    public void setInteger(String string, int i, int j)
    {
        if( i != j )
          m_hProperties.put(string, new ReadGuiListEntry( i ) );
    }
    
    public void setLong(String string, long i, long j)
    {
        if( i != j )
          m_hProperties.put(string, new ReadGuiListEntry(i));
    }
    
    public void setString(String string1, String string2, String string3)
    {
        if( string2 != null && !string2.equals(string3))
          m_hProperties.put(string1, new ReadGuiListEntry(string2, string3));
    }
    
    public void setOption(String string, marimba.persist.Options options, int i, int j)
    {
        if( i != j )
        {
            String string2 = options.get(i);
            m_hProperties.put(string, new ReadGuiListEntry(options, i, string2));
        }
        
    }
    
    public void setColor(String string, Color color1, Color color2)
    {
        if( color1 != null && !color1.equals(color2))
          m_hProperties.put(string,new ReadGuiListEntry(color1));
    }
    
    public void setFont(String string, Font font1, Font font2)
    {
        if( font1 != null && !font1.equals(font2))
          m_hProperties.put(string,new ReadGuiListEntry(font1));
    }
    
    public void setURL(String string1, String string2, String string3)
    {
        setString(string1, string2, string3);
    }
    

    public void setObject(String string, Object object1, Object object2)
    {
        if( object1 != null && !object1.equals(object2))
        {
            m_hProperties.put(string,new ReadGuiListEntry(object1));
        }
    }
    
   public void setByteArray(String string, byte ab1[], byte ab2[])
    {
        if( ab1 != null && ab1 != ab2 )
          m_hProperties.put(string, new ReadGuiListEntry(ab1));
    }
    
    public void setObjectArray(String string, int i, Object aobject[])
    {
    
        if( aobject != null )
        {
            m_hProperties.put(string, new ReadGuiListEntry(aobject));
        }
        
    }
    
    
    public boolean getBoolean(String string, boolean flag)
    {
        if( debug )
        {
            System.out.println("getBoolean " + string );
        }
        
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get( string );
        if( object != null )
          return object.booleanValue();
        return flag;
    }
    
    public int getInteger(String string, int i)
    {
        if( debug )
        {
            System.out.println("getInteger " + string );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get( string );
        if( object != null && object.intValue() != -1)
          return object.intValue();
        return i;
    }
    
    public long getLong(String string, long i)
    {
        if( debug )
        {
            System.out.println("getLong " + string );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(string);
        if( object != null && object.longValue() != -1)
          return object.longValue();
        return i;
    }
    
    public String getString(String string1, String string2)
    {
        String retval = null;
        if( debug )
        {
            System.out.println("getString " + string1 );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(string1);
        if( object != null && object.stringValue() != null)
            retval = object.stringValue();
        else
            retval = string2;
        return retval;
    }
    
    public int getOption(String string, marimba.persist.Options options, int i)
    {
        if( debug )
        {
            System.out.println("getOption " + string );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(string);
        String string2 = null;
        if( object != null && object.theDataType == object.typeOption)
           string2 = object.theOtherString;
        if( string2 != null )
          return options.get(string2);
        return i;
    }
    
    public Color getColor(String string, Color color)
    {
        if( debug )
        {
            System.out.println("getColor " + string );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(string);
        if( object != null && object.colorValue() != null)
          return object.colorValue();
        return color;
    }
    
    public Font getFont(String string, Font font)
    {
        if( debug )
        {
            System.out.println("getFont " + string );
        }       
        ReadGuiListEntry object = (ReadGuiListEntry)m_hProperties.get(string);
        if( object != null && object.fontValue() != null)
          return object.fontValue();
        return font;
    }
    
    public String getURL(String string1, String string2)
    {
        if( debug )
        {
            System.out.println("getURL " + string1 );
        }       
        return getString(string1, string2);
    }
    
    public Object getObject(String string, Object object)
    {
        if( debug )
        {
            System.out.println("getObject " + string );
        }       
        ReadGuiListEntry object1 = (ReadGuiListEntry)m_hProperties.get(string);
        if( object1 != null && object1.objectValue() != null)
        {
            Object obj = object1.objectValue();
            return object1.objectValue();           
        }
        return object;
    }
    
    public byte[] getByteArray(String string, byte ab[])
    {
        if( debug )
        {
            System.out.println("getByteArray " + string );
        }       
        ReadGuiListEntry b1 = (ReadGuiListEntry)m_hProperties.get(string);
        if( b1 != null && b1.byteArrayValue() != null)
          return b1.byteArrayValue();
        return ab;
    }
    
    public Object[] getObjectArray(String string, Object aobject[])
    {
        if( debug )
        {
            System.out.println("getObjectArray " + string );
        }       
        ReadGuiListEntry oba = (ReadGuiListEntry)m_hProperties.get(string);
        if( oba != null && oba.objectArrayValue() != null)
          return oba.objectArrayValue();
        return aobject;

    }
    
}
