/* FormatCharacter.java -- Implementation of AttributedCharacterIterator for
   formatters.
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */
package gnu.java.text;

import java.text.AttributedCharacterIterator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

/**
 * This class should not be put public and it is only intended to the
 * classes of the java.text package. Its aim is to build a segmented
 * character iterator by appending strings and adding attributes to
 * portions of strings. The code intends to do some optimization
 * concerning memory consumption and attribute access but at the
 * end it is only an AttributedCharacterIterator.
 *
 * @author Guilhem Lavaux <guilhem@kaffe.org>
 * @date November 22, 2003
 */
public class FormatCharacterIterator implements AttributedCharacterIterator
{
  private String formattedString;
  private int charIndex;
  private int attributeIndex;
  private int[] ranges;
  private HashMap[] attributes;
  private static final boolean DEBUG = false;

  /**
   * This constructor builds an empty iterated strings. The attributes
   * are empty and so is the string. However you may append strings
   * and attributes to this iterator.
   */
  public FormatCharacterIterator()
  {
    formattedString = "";
    ranges = new int[0];
    attributes = new HashMap[0];
  }

  /**
   * This constructor take a string <code>s</code>, a set of ranges
   * and the corresponding attributes. This is used to build an iterator.
   * The array <code>ranges</code> should be formatted as follow:
   * each element of <code>ranges</code> specifies the index in the string
   * until which the corresponding map of attributes at the same position
   * is applied. For example, if you have:
   * <pre>
   *   s = "hello";
   *   ranges = new int[] { 2, 6 };
   *   attributes = new HashMap[2];
   * </pre>
   * <code>"he"</code> will have the attributes <code>attributes[0]</code>,
   * <code>"llo"</code> the <code>attributes[1]</code>.
   */
  public FormatCharacterIterator (String s, int[] ranges, HashMap[] attributes)
  {
    formattedString = s;
    this.ranges = ranges;
    this.attributes = attributes;
  }

  /*
   * The following methods are inherited from AttributedCharacterIterator,
   * and thus are already documented.
   */

  public Set getAllAttributeKeys()
  {
    if (attributes != null && attributes[attributeIndex] != null)
      return attributes[attributeIndex].keySet();
    else
      return new HashSet();
  }

  public Map getAttributes()
  {
    if (attributes != null && attributes[attributeIndex] != null)
      return attributes[attributeIndex];
    else
      return new HashMap();
  }

  public Object getAttribute (AttributedCharacterIterator.Attribute attrib)
  {
    if (attributes != null && attributes[attributeIndex] != null)
      return attributes[attributeIndex].get (attrib);
    else
      return null;
  }

  public int getRunLimit(Set reqAttrs)
  {
    if (attributes == null)
      return formattedString.length();

    int currentAttrIndex = attributeIndex;
    Set newKeys;

    do
      {
        currentAttrIndex++;
        if (currentAttrIndex == attributes.length)
          return formattedString.length();
        if (attributes[currentAttrIndex] == null)
          break;
        newKeys = attributes[currentAttrIndex].keySet();
      }
    while (newKeys.containsAll (reqAttrs));

    return ranges[currentAttrIndex-1];
  }

  public int getRunLimit (AttributedCharacterIterator.Attribute attribute)
  {
    Set s = new HashSet();

    s.add (attribute);
    return getRunLimit (s);
  }

  public int getRunLimit()
  {
    if (attributes == null)
      return formattedString.length();
    if (attributes[attributeIndex] == null)
      {
        for (int i=attributeIndex+1;i<attributes.length;i++)
          if (attributes[i] != null)
            return ranges[i-1];
        return formattedString.length();
      }

    return getRunLimit (attributes[attributeIndex].keySet());
  }

  public int getRunStart (Set reqAttrs)
  {
    if (attributes == null)
      return formattedString.length();

    int currentAttrIndex = attributeIndex;
    Set newKeys = null;

    do
      {
        if (currentAttrIndex == 0)
          return 0;

        currentAttrIndex--;
        if (attributes[currentAttrIndex] == null)
          break;
        newKeys = attributes[currentAttrIndex].keySet();
      }
    while (newKeys.containsAll (reqAttrs));

    return (currentAttrIndex > 0) ? ranges[currentAttrIndex-1] : 0;
  }

  public int getRunStart()
  {
    if (attributes == null)
      return 0;

    if (attributes[attributeIndex] == null)
      {
        for (int i=attributeIndex;i>0;i--)
          if (attributes[i] != null)
            return ranges[attributeIndex-1];
        return 0;
      }

    return getRunStart (attributes[attributeIndex].keySet());
  }

  public int getRunStart (AttributedCharacterIterator.Attribute attribute)
  {
    Set s = new HashSet();

    s.add (attribute);
    return getRunStart (s);
  }

  public Object clone()
  {
    return new FormatCharacterIterator (formattedString, ranges, attributes);
  }

  /*
   * The following methods are inherited from CharacterIterator and thus
   * are already documented.
   */

  public char current()
  {
    return formattedString.charAt (charIndex);
  }

  public char first()
  {
    charIndex = 0;
    attributeIndex = 0;
    return formattedString.charAt (0);
  }

  public int getBeginIndex()
  {
    return 0;
  }

  public int getEndIndex()
  {
    return formattedString.length();
  }

  public int getIndex()
  {
    return charIndex;
  }

  public char last()
  {
    charIndex = formattedString.length()-1;
    if (attributes != null)
      attributeIndex = attributes.length-1;
    return formattedString.charAt (charIndex);
  }

  public char next()
  {
    charIndex++;
    if (charIndex >= formattedString.length())
      {
        charIndex = getEndIndex();
        return DONE;
      }
    if (attributes != null)
      {
        if (charIndex >= ranges[attributeIndex])
          attributeIndex++;
      }
    return formattedString.charAt (charIndex);
  }

  public char previous()
  {
    charIndex--;
    if (charIndex < 0)
      {
        charIndex = 0;
        return DONE;
      }

    if (attributes != null)
      {
        if (charIndex < ranges[attributeIndex])
          attributeIndex--;
      }
    return formattedString.charAt (charIndex);
  }

  public char setIndex (int position)
  {
    if (position < 0 || position > formattedString.length())
      throw new IllegalArgumentException ("position is out of range");

    charIndex = position;
    if (attributes != null)
      {
        for (attributeIndex=0;attributeIndex<attributes.length;
             attributeIndex++)
          if (ranges[attributeIndex] > charIndex)
            break;
        attributeIndex--;
      }
    if (charIndex == formattedString.length())
      return DONE;
    else
      return formattedString.charAt (charIndex);
  }

  /**
   * This method merge the specified attributes and ranges with the
   * internal tables. This method is in charge of the optimization
   * of tables. Two following sets of attributes are never the same.
   *
   * @see #FormatCharacterIterator()
   *
   * @param attributes the new array attributes to apply to the string.
   */
  public void mergeAttributes (HashMap[] attributes, int[] ranges)
  {
    Vector new_ranges = new Vector();
    Vector new_attributes = new Vector();
    int i = 0, j = 0;

    debug("merging " + attributes.length + " attrs");

    while (i < this.ranges.length && j < ranges.length)
      {
        if (this.attributes[i] != null)
          {
            new_attributes.add (this.attributes[i]);
            if (attributes[j] != null)
              this.attributes[i].putAll (attributes[j]);
          }
        else
          {
            new_attributes.add (attributes[j]);
          }
        if (this.ranges[i] == ranges[j])
          {
            new_ranges.add (new Integer (ranges[j]));
            i++;
            j++;
          }
        else if (this.ranges[i] < ranges[j])
          {
            new_ranges.add (new Integer (this.ranges[i]));
            i++;
          }
        else
          {
            new_ranges.add (new Integer (ranges[j]));
            j++;
          }
     }

    if (i != this.ranges.length)
      {
        for (;i<this.ranges.length;i++)
          {
            new_attributes.add (this.attributes[i]);
            new_ranges.add (new Integer (this.ranges[i]));
          }
      }
    if (j != ranges.length)
      {
        for (;j<ranges.length;j++)
          {
            new_attributes.add (attributes[j]);
            new_ranges.add (new Integer (ranges[j]));
          }
      }

    this.attributes = new HashMap[new_attributes.size()];
    this.ranges = new int[new_ranges.size()];
    System.arraycopy (new_attributes.toArray(), 0, this.attributes,
                      0, this.attributes.length);

    for (i=0;i<new_ranges.size();i++)
      {
        this.ranges[i] = ((Integer)new_ranges.elementAt (i)).intValue();
      }

    dumpTable();
  }

  /**
   * This method appends to the internal attributed string the attributed
   * string contained in the specified iterator.
   *
   * @param iterator the iterator which contains the attributed string to
   * append to this iterator.
   */
  public void append (AttributedCharacterIterator iterator)
  {
    char c = iterator.first();
    Vector more_ranges = new Vector();
    Vector more_attributes = new Vector();

    do
      {
        formattedString = formattedString + String.valueOf (c);
        // TODO: Reduce the size of the output array.
        more_attributes.add (iterator.getAttributes());
        more_ranges.add (new Integer (formattedString.length()));
        // END TOOD
        c = iterator.next();
      }
    while (c != DONE);

    HashMap[] new_attributes = new HashMap[attributes.length
                                           + more_attributes.size()];
    int[] new_ranges = new int[ranges.length + more_ranges.size()];

    System.arraycopy (attributes, 0, new_attributes, 0, attributes.length);
    System.arraycopy (more_attributes.toArray(), 0, new_attributes,
                      attributes.length, more_attributes.size());

    System.arraycopy (ranges, 0, new_ranges, 0, ranges.length);
    Object[] new_ranges_array = more_ranges.toArray();
    for (int i = 0; i < more_ranges.size();i++)
      new_ranges[i+ranges.length] = ((Integer) new_ranges_array[i]).intValue();

    attributes = new_attributes;
    ranges = new_ranges;
  }

  /**
   * This method appends an attributed string which attributes are specified
   * directly in the calling parameters.
   *
   * @param text The string to append.
   * @param local_attributes The attributes to put on this string in the
   * iterator. If it is <code>null</code> the string will simply have no
   * attributes.
   */
  public void append (String text, HashMap local_attributes)
  {
    int[] new_ranges = new int[ranges.length+1];
    HashMap[] new_attributes = new HashMap[attributes.length+1];

    formattedString += text;
    System.arraycopy (attributes, 0, new_attributes, 0, attributes.length);
    System.arraycopy (ranges, 0, new_ranges, 0, ranges.length);
    new_ranges[ranges.length] = formattedString.length();
    new_attributes[attributes.length] = local_attributes;

    ranges = new_ranges;
    attributes = new_attributes;
  }

  /**
   * This method appends a string without attributes. It is completely
   * equivalent to call {@link #append(String,HashMap)} with local_attributes
   * equal to <code>null</code>.
   *
   * @param text The string to append to the iterator.
   */
  public void append (String text)
  {
    append (text, null);
  }

  /**
   * This method adds a set of attributes to a range of character. The
   * bounds are always inclusive. In the case many attributes have to
   * be added it is advised to directly use {@link #mergeAttributes([Ljava.util.HashMap;[I}
   *
   * @param attributes Attributes to merge into the iterator.
   * @param range_start Lower bound of the range of characters which will receive the
   * attribute.
   * @param range_end Upper bound of the range of characters which will receive the
   * attribute.
   *
   * @throws IllegalArgumentException if ranges are out of bounds.
   */
  public void addAttributes(HashMap attributes, int range_start, int range_end)
  {
    if (range_start == 0)
      mergeAttributes(new HashMap[] { attributes }, new int[] { range_end });
    else
      mergeAttributes(new HashMap[] { null, attributes }, new int[] { range_start, range_end });
  }

  private void debug(String s)
  {
    if (DEBUG)
      System.out.println(s);
  }

  private void dumpTable()
  {
    int start_range = 0;

    if (!DEBUG)
      return;

    System.out.println("Dumping internal table:");
    for (int i = 0; i < ranges.length; i++)
      {
        System.out.print("\t" + start_range + " => " + ranges[i] + ":");
        if (attributes[i] == null)
          System.out.println("null");
        else
          {
            Set keyset = attributes[i].keySet();
            if (keyset != null)
              {
                Iterator keys = keyset.iterator();

                while (keys.hasNext())
                  System.out.print(" " + keys.next());
              }
            else
              System.out.println("keySet null");
            System.out.println();
          }
      }
    System.out.println();
    System.out.flush();
  }
}
