/* StringContent.java --
   Copyright (C) 2005, 2006 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 javax.swing.text;

import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEdit;

/**
 * An implementation of the <code>AbstractDocument.Content</code>
 * interface useful for small documents or debugging. The character
 * content is a simple character array. It's not really efficient.
 *
 * <p>Do not use this class for large size.</p>
 */
public final class StringContent
  implements AbstractDocument.Content, Serializable
{
  /**
   * Stores a reference to a mark that can be resetted to the original value
   * after a mark has been moved. This is used for undoing actions.
   */
  private class UndoPosRef
  {
    /**
     * The mark that might need to be reset.
     */
    private Mark mark;

    /**
     * The original offset to reset the mark to.
     */
    private int undoOffset;

    /**
     * Creates a new UndoPosRef.
     *
     * @param m the mark
     */
    UndoPosRef(Mark m)
    {
      mark = m;
      undoOffset = mark.mark;
    }

    /**
     * Resets the position of the mark to the value that it had when
     * creating this UndoPosRef.
     */
    void reset()
    {
      mark.mark = undoOffset;
    }
  }

  /**
   * Holds a mark into the buffer that is used by StickyPosition to find
   * the actual offset of the position. This is pulled out of the
   * GapContentPosition object so that the mark and position can be handled
   * independently, and most important, so that the StickyPosition can
   * be garbage collected while we still hold a reference to the Mark object.
   */
  private class Mark
  {
    /**
     * The actual mark into the buffer.
     */
    int mark;


    /**
     * The number of GapContentPosition object that reference this mark. If
     * it reaches zero, it get's deleted by
     * {@link StringContent#garbageCollect()}.
     */
    int refCount;

    /**
     * Creates a new Mark object for the specified offset.
     *
     * @param offset the offset
     */
    Mark(int offset)
    {
      mark = offset;
    }
  }

  /** The serialization UID (compatible with JDK1.5). */
  private static final long serialVersionUID = 4755994433709540381L;

  // This is package-private to avoid an accessor method.
  char[] content;

  private int count;

  /**
   * Holds the marks for the positions.
   *
   * This is package private to avoid accessor methods.
   */
  Vector marks;

  private class InsertUndo extends AbstractUndoableEdit
  {
    private int start;

    private int length;

    private String redoContent;

    private Vector positions;

    public InsertUndo(int start, int length)
    {
      super();
      this.start = start;
      this.length = length;
    }

    public void undo()
    {
      super.undo();
      try
        {
          if (marks != null)
            positions = getPositionsInRange(null, start, length);
          redoContent = getString(start, length);
          remove(start, length);
        }
      catch (BadLocationException b)
        {
          throw new CannotUndoException();
        }
    }

    public void redo()
    {
      super.redo();
      try
        {
          insertString(start, redoContent);
          redoContent = null;
          if (positions != null)
            {
              updateUndoPositions(positions);
              positions = null;
            }
        }
      catch (BadLocationException b)
        {
          throw new CannotRedoException();
        }
    }
  }

  private class RemoveUndo extends AbstractUndoableEdit
  {
    private int start;
    private int len;
    private String undoString;

    Vector positions;

    public RemoveUndo(int start, String str)
    {
      super();
      this.start = start;
      len = str.length();
      this.undoString = str;
      if (marks != null)
        positions = getPositionsInRange(null, start, str.length());
    }

    public void undo()
    {
      super.undo();
      try
        {
          StringContent.this.insertString(this.start, this.undoString);
          if (positions != null)
            {
              updateUndoPositions(positions);
              positions = null;
            }
          undoString = null;
        }
      catch (BadLocationException bad)
        {
          throw new CannotUndoException();
        }
    }

    public void redo()
    {
      super.redo();
      try
        {
          undoString = getString(start, len);
          if (marks != null)
            positions = getPositionsInRange(null, start, len);
          remove(this.start, len);
        }
      catch (BadLocationException bad)
        {
          throw new CannotRedoException();
        }
    }
  }

  private class StickyPosition implements Position
  {
    Mark mark;

    public StickyPosition(int offset)
    {
      // Try to make space.
      garbageCollect();

      mark = new Mark(offset);
      mark.refCount++;
      marks.add(mark);

      new WeakReference(this, queueOfDeath);
    }

    /**
     * Should be >=0.
     */
    public int getOffset()
    {
      return mark.mark;
    }
  }

  /**
   * Used in {@link #remove(int,int)}.
   */
  private static final char[] EMPTY = new char[0];

  /**
   * Queues all references to GapContentPositions that are about to be
   * GC'ed. This is used to remove the corresponding marks from the
   * positionMarks array if the number of references to that mark reaches zero.
   *
   * This is package private to avoid accessor synthetic methods.
   */
  ReferenceQueue queueOfDeath;

  /**
   * Creates a new instance containing the string "\n".  This is equivalent
   * to calling {@link #StringContent(int)} with an <code>initialLength</code>
   * of 10.
   */
  public StringContent()
  {
    this(10);
  }

  /**
   * Creates a new instance containing the string "\n".
   *
   * @param initialLength  the initial length of the underlying character
   *                       array used to store the content.
   */
  public StringContent(int initialLength)
  {
    super();
    queueOfDeath = new ReferenceQueue();
    if (initialLength < 1)
      initialLength = 1;
    this.content = new char[initialLength];
    this.content[0] = '\n';
    this.count = 1;
  }

  protected Vector getPositionsInRange(Vector v,
                                       int offset,
                                       int length)
  {
    Vector refPos = v == null ? new Vector() : v;
    Iterator iter = marks.iterator();
    while(iter.hasNext())
      {
        Mark m = (Mark) iter.next();
        if (offset <= m.mark && m.mark <= offset + length)
          refPos.add(new UndoPosRef(m));
      }
    return refPos;
  }

  /**
   * Creates a position reference for the character at the given offset.  The
   * position offset will be automatically updated when new characters are
   * inserted into or removed from the content.
   *
   * @param offset  the character offset.
   *
   * @throws BadLocationException if offset is outside the bounds of the
   *         content.
   */
  public Position createPosition(int offset) throws BadLocationException
  {
    // Lazily create marks vector.
    if (marks == null)
      marks = new Vector();
    StickyPosition sp = new StickyPosition(offset);
    return sp;
  }

  /**
   * Returns the length of the string content, including the '\n' character at
   * the end.
   *
   * @return The length of the string content.
   */
  public int length()
  {
    return count;
  }

  /**
   * Inserts <code>str</code> at the given position and returns an
   * {@link UndoableEdit} that enables undo/redo support.
   *
   * @param where  the insertion point (must be less than
   *               <code>length()</code>).
   * @param str  the string to insert (<code>null</code> not permitted).
   *
   * @return An object that can undo the insertion.
   */
  public UndoableEdit insertString(int where, String str)
    throws BadLocationException
  {
    checkLocation(where, 0);
    if (where == this.count)
      throw new BadLocationException("Invalid location", 1);
    if (str == null)
      throw new NullPointerException();
    char[] insert = str.toCharArray();
    replace(where, 0, insert);

    // Move all the positions.
    if (marks != null)
      {
        Iterator iter = marks.iterator();
        int start = where;
        if (start == 0)
          start = 1;
        while (iter.hasNext())
          {
            Mark m = (Mark) iter.next();
            if (m.mark >= start)
              m.mark += str.length();
          }
      }

    InsertUndo iundo = new InsertUndo(where, insert.length);
    return iundo;
  }

  /**
   * Removes the specified range of characters and returns an
   * {@link UndoableEdit} that enables undo/redo support.
   *
   * @param where  the starting index.
   * @param nitems  the number of characters.
   *
   * @return An object that can undo the removal.
   *
   * @throws BadLocationException if the character range extends outside the
   *         bounds of the content OR includes the last character.
   */
  public UndoableEdit remove(int where, int nitems) throws BadLocationException
  {
    checkLocation(where, nitems + 1);
    RemoveUndo rundo = new RemoveUndo(where, new String(this.content, where,
        nitems));

    replace(where, nitems, EMPTY);
    // Move all the positions.
    if (marks != null)
      {
        Iterator iter = marks.iterator();
        while (iter.hasNext())
          {
            Mark m = (Mark) iter.next();
            if (m.mark >= where + nitems)
              m.mark -= nitems;
            else if (m.mark >= where)
              m.mark = where;
          }
      }
    return rundo;
  }

  private void replace(int offs, int numRemove, char[] insert)
  {
    int insertLength = insert.length;
    int delta = insertLength - numRemove;
    int src = offs + numRemove;
    int numMove = count - src;
    int dest = src + delta;
    if (count + delta >= content.length)
      {
        // Grow data array.
        int newLength = Math.max(2 * content.length, count + delta);
        char[] newContent = new char[newLength];
        System.arraycopy(content, 0, newContent, 0, offs);
        System.arraycopy(insert, 0, newContent, offs, insertLength);
        System.arraycopy(content, src, newContent, dest, numMove);
        content = newContent;
      }
    else
      {
        System.arraycopy(content, src, content, dest, numMove);
        System.arraycopy(insert, 0, content, offs, insertLength);
      }
    count += delta;
  }

  /**
   * Returns a new <code>String</code> containing the characters in the
   * specified range.
   *
   * @param where  the start index.
   * @param len  the number of characters.
   *
   * @return A string.
   *
   * @throws BadLocationException if the requested range of characters extends
   *         outside the bounds of the content.
   */
  public String getString(int where, int len) throws BadLocationException
  {
    // The RI throws a StringIndexOutOfBoundsException here, which
    // smells like a bug. We throw a BadLocationException instead.
    checkLocation(where, len);
    return new String(this.content, where, len);
  }

  /**
   * Updates <code>txt</code> to contain a direct reference to the underlying
   * character array.
   *
   * @param where  the index of the first character.
   * @param len  the number of characters.
   * @param txt  a carrier for the return result (<code>null</code> not
   *             permitted).
   *
   * @throws BadLocationException if the requested character range is not
   *                              within the bounds of the content.
   * @throws NullPointerException if <code>txt</code> is <code>null</code>.
   */
  public void getChars(int where, int len, Segment txt)
    throws BadLocationException
  {
    if (where + len > count)
      throw new BadLocationException("Invalid location", where + len);
    txt.array = content;
    txt.offset = where;
    txt.count = len;
  }


  /**
   * Resets the positions in the specified vector to their original offset
   * after a undo operation is performed. For example, after removing some
   * content, the positions in the removed range will all be set to one
   * offset. This method restores the positions to their original offsets
   * after an undo.
   */
  protected void updateUndoPositions(Vector positions)
  {
    for (Iterator i = positions.iterator(); i.hasNext();)
      {
        UndoPosRef pos = (UndoPosRef) i.next();
        pos.reset();
      }
  }

  /**
   * A utility method that checks the validity of the specified character
   * range.
   *
   * @param where  the first character in the range.
   * @param len  the number of characters in the range.
   *
   * @throws BadLocationException if the specified range is not within the
   *         bounds of the content.
   */
  void checkLocation(int where, int len) throws BadLocationException
  {
    if (where < 0)
      throw new BadLocationException("Invalid location", 1);
    else if (where > this.count)
      throw new BadLocationException("Invalid location", this.count);
    else if ((where + len) > this.count)
      throw new BadLocationException("Invalid range", this.count);
  }

  /**
   * Polls the queue of death for GapContentPositions, updates the
   * corresponding reference count and removes the corresponding mark
   * if the refcount reaches zero.
   *
   * This is package private to avoid accessor synthetic methods.
   */
  void garbageCollect()
  {
    Reference ref = queueOfDeath.poll();
    while (ref != null)
      {
        if (ref != null)
          {
            StickyPosition pos = (StickyPosition) ref.get();
            Mark m = pos.mark;
            m.refCount--;
            if (m.refCount == 0)
              marks.remove(m);
          }
        ref = queueOfDeath.poll();
      }
  }
}
