/* CharsetEncoder.java -- 
   Copyright (C) 2002 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 java.nio.charset;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

/**
 * @author Jesse Rosenstock
 * @since 1.4
 */
public abstract class CharsetEncoder
{
  private static final int STATE_RESET   = 0;
  private static final int STATE_CODING  = 1;
  private static final int STATE_END     = 2;
  private static final int STATE_FLUSHED = 3;
  
  private static final byte[] DEFAULT_REPLACEMENT = {(byte)'?'};

  private final Charset charset;
  private final float averageBytesPerChar;
  private final float maxBytesPerChar;
  private byte[] replacement;

  private int state = STATE_RESET;

  private CodingErrorAction malformedInputAction
    = CodingErrorAction.REPORT;
  private CodingErrorAction unmappableCharacterAction
    = CodingErrorAction.REPORT;

  protected CharsetEncoder (Charset cs, float averageBytesPerChar,
                            float maxBytesPerChar)
  {
    this (cs, averageBytesPerChar, maxBytesPerChar, DEFAULT_REPLACEMENT);
  }

  protected CharsetEncoder (Charset cs, float averageBytesPerChar, 
                            float maxBytesPerChar, byte[] replacement)
  {
    if (averageBytesPerChar <= 0.0f)
      throw new IllegalArgumentException ("Non-positive averageBytesPerChar");
    if (maxBytesPerChar <= 0.0f)
      throw new IllegalArgumentException ("Non-positive maxBytesPerChar");

    this.charset = cs;
    this.averageBytesPerChar
      = averageBytesPerChar;
    this.maxBytesPerChar
      = maxBytesPerChar;
    this.replacement = replacement;
    implReplaceWith (replacement);
  }
 
  public final float averageBytesPerChar ()
  {
    return averageBytesPerChar;
  }

  public boolean canEncode (char c)
  {
    CharBuffer cb = CharBuffer.allocate (1).put (c);
    cb.flip ();
    return canEncode (cb);
  }

  public boolean canEncode (CharSequence cs)
  {
    CharBuffer cb;
    if (cs instanceof CharBuffer)
      cb = ((CharBuffer) cs).duplicate ();
    else
      cb = CharBuffer.wrap (cs);
    return canEncode (cb);
  }

  private boolean canEncode (CharBuffer cb)
  {
    // It is an error if a coding operation is "in progress"
    // I take that to mean the state is not reset or flushed.
    // XXX: check "in progress" everywhere
    if (state == STATE_FLUSHED)
      reset ();
    else if (state != STATE_RESET)
      throw new IllegalStateException ();

    CodingErrorAction oldMalformedInputAction = malformedInputAction;
    CodingErrorAction oldUnmappableCharacterAction
      = unmappableCharacterAction;

    try
      {
        if (oldMalformedInputAction != CodingErrorAction.REPORT)
          onMalformedInput (CodingErrorAction.REPORT);
        if (oldUnmappableCharacterAction != CodingErrorAction.REPORT)
          onUnmappableCharacter (CodingErrorAction.REPORT);
      }
    catch (Exception e)
      {
        return false;
      }
    finally
      {
        if (oldMalformedInputAction != CodingErrorAction.REPORT)
          onMalformedInput (oldMalformedInputAction);
        if (oldUnmappableCharacterAction != CodingErrorAction.REPORT)
          onUnmappableCharacter (oldUnmappableCharacterAction);
      }

    return true;
  }

  public final Charset charset ()
  {
    return charset;
  }

  public final ByteBuffer encode (CharBuffer in)
    throws CharacterCodingException
  {
    // XXX: Sun's Javadoc seems to contradict itself saying an
    // IllegalStateException is thrown "if a decoding operation is already
    // in progress" and also that "it resets this Encoder".
    // Should we check to see that the state is reset, or should we
    // call reset()?
    if (state != STATE_RESET)
      throw new IllegalStateException ();

    // REVIEW: Using max instead of average may allocate a very large
    // buffer.  Maybe we should do something more efficient?
    int remaining = in.remaining ();
    int n = (int) (remaining * maxBytesPerChar ());
    ByteBuffer out = ByteBuffer.allocate (n);

    if (remaining == 0)
      {
        state = STATE_FLUSHED;
        return out;
      }

    CoderResult cr = encode (in, out, true);
    if (cr.isError ())
      cr.throwException ();

    cr = flush (out);
    if (cr.isError ())
      cr.throwException ();

    out.flip ();

    // Unfortunately, resizing the actual bytebuffer array is required.
    byte[] resized = new byte[out.remaining()];
    out.get(resized);
    return ByteBuffer.wrap(resized);
  }

  public final CoderResult encode (CharBuffer in, ByteBuffer out,
                                   boolean endOfInput)
  {
    int newState = endOfInput ? STATE_END : STATE_CODING;
    // XXX: Need to check for "previous step was an invocation [not] of
    // this method with a value of true for the endOfInput parameter but
    // a return value indicating an incomplete decoding operation"
    // XXX: We will not check the previous return value, just
    // that the previous call passed true for endOfInput
    if (state != STATE_RESET && state != STATE_CODING
        && !(endOfInput && state == STATE_END))
      throw new IllegalStateException ();
    state = newState;

    for (;;)
      {
        CoderResult cr;
        try
          {
            cr = encodeLoop (in, out);
          }
        catch (RuntimeException e)
          {
            throw new CoderMalfunctionError (e);
          }

        if (cr.isOverflow ())
          return cr;

        if (cr.isUnderflow ())
          {
            if (endOfInput && in.hasRemaining ())
              cr = CoderResult.malformedForLength (in.remaining ());
            else
              return cr;
          }

        CodingErrorAction action = cr.isMalformed ()
                                     ? malformedInputAction
                                     : unmappableCharacterAction;

        if (action == CodingErrorAction.REPORT)
          return cr;

        if (action == CodingErrorAction.REPLACE)
          {
            if (out.remaining () < replacement.length)
              return CoderResult.OVERFLOW;
            out.put (replacement);
          }

        in.position (in.position () + cr.length ());
      }
  }

  protected abstract CoderResult encodeLoop (CharBuffer in, ByteBuffer out);

  public final CoderResult flush (ByteBuffer out)
  {
    // It seems weird that you can flush after reset, but Sun's javadoc
    // says an IllegalStateException is thrown "If the previous step of the
    // current decoding operation was an invocation neither of the reset
    // method nor ... of the three-argument encode method with a value of
    // true for the endOfInput parameter."
    // Further note that flush() only requires that there not be
    // an IllegalStateException if the previous step was a call to
    // encode with true as the last argument.  It does not require
    // that the call succeeded.  encode() does require that it succeeded.
    // XXX: test this to see if reality matches javadoc
    if (state != STATE_RESET && state != STATE_END)
      throw new IllegalStateException ();

    state = STATE_FLUSHED;
    return implFlush (out);
  }

  protected CoderResult implFlush (ByteBuffer out)
  {
    return CoderResult.UNDERFLOW;
  }

  protected void implOnMalformedInput (CodingErrorAction newAction)
  {
    // default implementation does nothing
  }

  protected void implOnUnmappableCharacter (CodingErrorAction newAction)
  {
    // default implementation does nothing
  }

  protected void implReplaceWith (byte[] newReplacement)
  {
    // default implementation does nothing
  }

  protected void implReset ()
  {
    // default implementation does nothing
  }

  public boolean isLegalReplacement (byte[] replacement)
  {
    // TODO: cache the decoder
    // error actions will be REPORT after construction
    CharsetDecoder decoder = charset.newDecoder ();
    ByteBuffer bb = ByteBuffer.wrap (replacement);
    CharBuffer cb
      = CharBuffer.allocate ((int) (replacement.length
                                    * decoder.maxCharsPerByte ()));
    return !decoder.decode (bb, cb, true).isError ();
  }

  public CodingErrorAction malformedInputAction ()
  {
    return malformedInputAction;
  }

  public final float maxBytesPerChar ()
  {
    return maxBytesPerChar;
  }

  public final CharsetEncoder onMalformedInput (CodingErrorAction newAction)
  {
    if (newAction == null)
      throw new IllegalArgumentException ("Null action");

    malformedInputAction = newAction;
    implOnMalformedInput (newAction);
    return this;
  }

  public CodingErrorAction unmappableCharacterAction ()
  {
    return unmappableCharacterAction;
  }

  public final CharsetEncoder onUnmappableCharacter
    (CodingErrorAction newAction)
  {
    if (newAction == null)
      throw new IllegalArgumentException ("Null action");

    unmappableCharacterAction = newAction;
    implOnUnmappableCharacter (newAction);
    return this;
  }

  public final byte[] replacement ()
  {
    return replacement;
  }

  public final CharsetEncoder replaceWith (byte[] newReplacement)
  {
    if (newReplacement == null)
      throw new IllegalArgumentException ("Null replacement");
    if (newReplacement.length == 0)
      throw new IllegalArgumentException ("Empty replacement");
    // XXX: what about maxBytesPerChar?

      if (!isLegalReplacement (newReplacement))
        throw new IllegalArgumentException ("Illegal replacement");

    this.replacement = newReplacement;
    implReplaceWith (newReplacement);
    return this;
  }

  public final CharsetEncoder reset ()
  {
    state = STATE_RESET;
    implReset ();
    return this;
  }
}
