/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.tomcat.util.buf;

import java.io.IOException;
import java.io.Serializable;

/**
 * Utilities to manipluate char chunks. While String is
 * the easiest way to manipulate chars ( search, substrings, etc),
 * it is known to not be the most efficient solution - Strings are
 * designed as imutable and secure objects.
 * 
 * @author dac@sun.com
 * @author James Todd [gonzo@sun.com]
 * @author Costin Manolache
 * @author Remy Maucherat
 */
public final class CharChunk implements Cloneable, Serializable, CharSequence {

    // Input interface, used when the buffer is emptied.
    public static interface CharInputChannel {
        /** 
         * Read new bytes ( usually the internal conversion buffer ).
         * The implementation is allowed to ignore the parameters, 
         * and mutate the chunk if it wishes to implement its own buffering.
         */
        public int realReadChars(char cbuf[], int off, int len)
            throws IOException;
    }
    /**
     *  When we need more space we'll either
     *  grow the buffer ( up to the limit ) or send it to a channel.
     */
    public static interface CharOutputChannel {
        /** Send the bytes ( usually the internal conversion buffer ).
         *  Expect 8k output if the buffer is full.
         */
        public void realWriteChars(char cbuf[], int off, int len)
            throws IOException;
    }
    
    // -------------------- 
    // char[]
    private char buff[];

    private int start;
    private int end;

    private boolean isSet=false;  // XXX 

    // -1: grow undefinitely
    // maximum amount to be cached
    private int limit=-1;

    private CharInputChannel in = null;
    private CharOutputChannel out = null;
    
    private boolean optimizedWrite=true;

    /**
     * Creates a new, uninitialized CharChunk object.
     */
    public CharChunk() {
    }

    public CharChunk(int size) {
        allocate( size, -1 );
    }

    // --------------------
    
    public CharChunk getClone() {
        try {
            return (CharChunk)this.clone();
        } catch( Exception ex) {
            return null;
        }
    }

    public boolean isNull() {
        if( end > 0 ) return false;
        return !isSet; //XXX 
    }
    
    /**
     * Resets the message bytes to an uninitialized state.
     */
    public void recycle() {
        //        buff=null;
        isSet=false; // XXX
        start=0;
        end=0;
    }

    public void reset() {
        buff=null;
    }

    // -------------------- Setup --------------------

    public void allocate( int initial, int limit  ) {
        if( buff==null || buff.length < initial ) {
            buff=new char[initial];
        }
        this.limit=limit;
        start=0;
        end=0;
        isSet=true;
    }


    public void setOptimizedWrite(boolean optimizedWrite) {
        this.optimizedWrite = optimizedWrite;
    }

    public void setChars( char[] c, int off, int len ) {
        buff=c;
        start=off;
        end=start + len;
        isSet=true;
    }

    /** Maximum amount of data in this buffer.
     *
     *  If -1 or not set, the buffer will grow undefinitely.
     *  Can be smaller than the current buffer size ( which will not shrink ).
     *  When the limit is reached, the buffer will be flushed ( if out is set )
     *  or throw exception.
     */
    public void setLimit(int limit) {
        this.limit=limit;
    }
    
    public int getLimit() {
        return limit;
    }

    /**
     * When the buffer is empty, read the data from the input channel.
     */
    public void setCharInputChannel(CharInputChannel in) {
        this.in = in;
    }

    /** When the buffer is full, write the data to the output channel.
     *         Also used when large amount of data is appended.
     *
     *  If not set, the buffer will grow to the limit.
     */
    public void setCharOutputChannel(CharOutputChannel out) {
        this.out=out;
    }

    // compat 
    public char[] getChars()
    {
        return getBuffer();
    }
    
    public char[] getBuffer()
    {
        return buff;
    }
    
    /**
     * Returns the start offset of the bytes.
     * For output this is the end of the buffer.
     */
    public int getStart() {
        return start;
    }
    
    public int getOffset() {
        return start;
    }

    /**
     * Returns the start offset of the bytes.
     */
    public void setOffset(int off) {
        start=off;
    }

    /**
     * Returns the length of the bytes.
     */
    public int getLength() {
        return end-start;
    }


    public int getEnd() {
        return end;
    }

    public void setEnd( int i ) {
        end=i;
    }

    // -------------------- Adding data --------------------
    
    public void append( char b )
        throws IOException
    {
        makeSpace( 1 );

        // couldn't make space
        if( limit >0 && end >= limit ) {
            flushBuffer();
        }
        buff[end++]=b;
    }
    
    public void append( CharChunk src )
        throws IOException
    {
        append( src.getBuffer(), src.getOffset(), src.getLength());
    }

    /** Add data to the buffer
     */
    public void append( char src[], int off, int len )
        throws IOException
    {
        // will grow, up to limit
        makeSpace( len );

        // if we don't have limit: makeSpace can grow as it wants
        if( limit < 0 ) {
            // assert: makeSpace made enough space
            System.arraycopy( src, off, buff, end, len );
            end+=len;
            return;
        }

        // Optimize on a common case.
        // If the source is going to fill up all the space in buffer, may
        // as well write it directly to the output, and avoid an extra copy
        if ( optimizedWrite && len == limit && end == start && out != null ) {
            out.realWriteChars( src, off, len );
            return;
        }
        
        // if we have limit and we're below
        if( len <= limit - end ) {
            // makeSpace will grow the buffer to the limit,
            // so we have space
            System.arraycopy( src, off, buff, end, len );
            
            end+=len;
            return;
        }

        // need more space than we can afford, need to flush
        // buffer

        // the buffer is already at ( or bigger than ) limit
        
        // Optimization:
        // If len-avail < length ( i.e. after we fill the buffer with
        // what we can, the remaining will fit in the buffer ) we'll just
        // copy the first part, flush, then copy the second part - 1 write
        // and still have some space for more. We'll still have 2 writes, but
        // we write more on the first.

        if( len + end < 2 * limit ) {
            /* If the request length exceeds the size of the output buffer,
               flush the output buffer and then write the data directly.
               We can't avoid 2 writes, but we can write more on the second
            */
            int avail=limit-end;
            System.arraycopy(src, off, buff, end, avail);
            end += avail;
            
            flushBuffer();
            
            System.arraycopy(src, off+avail, buff, end, len - avail);
            end+= len - avail;
            
        } else if(optimizedWrite) { // len > buf.length + avail & we have a real sink
            // long write - flush the buffer and write the rest
            // directly from source
            flushBuffer();
            
            out.realWriteChars( src, off, len );
        } else { // ugly but it works for fake sinks if they reset us
            flushBuffer();
            append(src, off, len);
        }
    }


    /** Add data to the buffer
     */
    public void append( StringBuffer sb )
        throws IOException
    {
        int len=sb.length();

        // will grow, up to limit
        makeSpace( len );

        // if we don't have limit: makeSpace can grow as it wants
        if( limit < 0 ) {
            // assert: makeSpace made enough space
            sb.getChars(0, len, buff, end );
            end+=len;
            return;
        }

        int off=0;
        int sbOff = off;
        int sbEnd = off + len;
        while (sbOff < sbEnd) {
            int d = min(limit - end, sbEnd - sbOff);
            sb.getChars( sbOff, sbOff+d, buff, end);
            sbOff += d;
            end += d;
            if (end >= limit)
                flushBuffer();
        }
    }

    /** Append a string to the buffer
     */
    public void append(String s) throws IOException {
        append(s, 0, s.length());
    }
    
    /** Append a string to the buffer
     */
    public void append(String s, int off, int len) throws IOException {
        if (s==null) return;
        
        // will grow, up to limit
        makeSpace( len );

        // if we don't have limit: makeSpace can grow as it wants
        if( limit < 0 ) {
            // assert: makeSpace made enough space
            s.getChars(off, off+len, buff, end );
            end+=len;
            return;
        }

        int sOff = off;
        int sEnd = off + len;
        while (sOff < sEnd) {
            int d = min(limit - end, sEnd - sOff);
            s.getChars( sOff, sOff+d, buff, end);
            sOff += d;
            end += d;
            if (end >= limit)
                flushBuffer();
        }
    }
    
    // -------------------- Removing data from the buffer --------------------

    public int substract()
        throws IOException {

        if ((end - start) == 0) {
            if (in == null)
                return -1;
            int n = in.realReadChars(buff, end, buff.length - end);
            if (n < 0)
                return -1;
        }

        return (buff[start++]);

    }

    public int substract(CharChunk src)
        throws IOException {

        if ((end - start) == 0) {
            if (in == null)
                return -1;
            int n = in.realReadChars( buff, end, buff.length - end);
            if (n < 0)
                return -1;
        }

        int len = getLength();
        src.append(buff, start, len);
        start = end;
        return len;

    }

    public int substract( char src[], int off, int len )
        throws IOException {

        if ((end - start) == 0) {
            if (in == null)
                return -1;
            int n = in.realReadChars( buff, end, buff.length - end);
            if (n < 0)
                return -1;
        }

        int n = len;
        if (len > getLength()) {
            n = getLength();
        }
        System.arraycopy(buff, start, src, off, n);
        start += n;
        return n;

    }


    public void flushBuffer()
        throws IOException
    {
        //assert out!=null
        if( out==null ) {
            throw new IOException( "Buffer overflow, no sink " + limit + " " +
                                   buff.length  );
        }
        out.realWriteChars( buff, start, end - start );
        end=start;
    }

    /** Make space for len chars. If len is small, allocate
     *        a reserve space too. Never grow bigger than limit.
     */
    private void makeSpace(int count)
    {
        char[] tmp = null;

        int newSize;
        int desiredSize=end + count;

        // Can't grow above the limit
        if( limit > 0 &&
            desiredSize > limit) {
            desiredSize=limit;
        }

        if( buff==null ) {
            if( desiredSize < 256 ) desiredSize=256; // take a minimum
            buff=new char[desiredSize];
        }

        // limit < buf.length ( the buffer is already big )
        // or we already have space XXX
        if( desiredSize <= buff.length) {
            return;
        }
        // grow in larger chunks
        if( desiredSize < 2 * buff.length ) {
            newSize= buff.length * 2;
            if( limit >0 &&
                newSize > limit ) newSize=limit;
            tmp=new char[newSize];
        } else {
            newSize= buff.length * 2 + count ;
            if( limit > 0 &&
                newSize > limit ) newSize=limit;
            tmp=new char[newSize];
        }
        
        System.arraycopy(buff, 0, tmp, 0, end);
        buff = tmp;
        tmp = null;
    }
    
    // -------------------- Conversion and getters --------------------

    public String toString() {
        if (null == buff) {
            return null;
        } else if (end-start == 0) {
            return "";
        }
        return StringCache.toString(this);
    }
    
    public String toStringInternal() {
        return new String(buff, start, end-start);
    }

    public int getInt()
    {
        return Ascii.parseInt(buff, start,
                                end-start);
    }
    
    // -------------------- equals --------------------

    /**
     * Compares the message bytes to the specified String object.
     * @param s the String to compare
     * @return true if the comparison succeeded, false otherwise
     */
    public boolean equals(String s) {
        char[] c = buff;
        int len = end-start;
        if (c == null || len != s.length()) {
            return false;
        }
        int off = start;
        for (int i = 0; i < len; i++) {
            if (c[off++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Compares the message bytes to the specified String object.
     * @param s the String to compare
     * @return true if the comparison succeeded, false otherwise
     */
    public boolean equalsIgnoreCase(String s) {
        char[] c = buff;
        int len = end-start;
        if (c == null || len != s.length()) {
            return false;
        }
        int off = start;
        for (int i = 0; i < len; i++) {
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public boolean equals(CharChunk cc) {
        return equals( cc.getChars(), cc.getOffset(), cc.getLength());
    }

    public boolean equals(char b2[], int off2, int len2) {
        char b1[]=buff;
        if( b1==null && b2==null ) return true;
        
        if (b1== null || b2==null || end-start != len2) {
            return false;
        }
        int off1 = start;
        int len=end-start;
        while ( len-- > 0) {
            if (b1[off1++] != b2[off2++]) {
                return false;
            }
        }
        return true;
    }

    public boolean equals(byte b2[], int off2, int len2) {
        char b1[]=buff;
        if( b2==null && b1==null ) return true;

        if (b1== null || b2==null || end-start != len2) {
            return false;
        }
        int off1 = start;
        int len=end-start;
        
        while ( len-- > 0) {
            if ( b1[off1++] != (char)b2[off2++]) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Returns true if the message bytes starts with the specified string.
     * @param s the string
     */
    public boolean startsWith(String s) {
        char[] c = buff;
        int len = s.length();
        if (c == null || len > end-start) {
            return false;
        }
        int off = start;
        for (int i = 0; i < len; i++) {
            if (c[off++] != s.charAt(i)) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * Returns true if the message bytes starts with the specified string.
     * @param s the string
     */
    public boolean startsWithIgnoreCase(String s, int pos) {
        char[] c = buff;
        int len = s.length();
        if (c == null || len+pos > end-start) {
            return false;
        }
        int off = start+pos;
        for (int i = 0; i < len; i++) {
            if (Ascii.toLower( c[off++] ) != Ascii.toLower( s.charAt(i))) {
                return false;
            }
        }
        return true;
    }
    

    // -------------------- Hash code  --------------------

    // normal hash. 
    public int hash() {
        int code=0;
        for (int i = start; i < start + end-start; i++) {
            code = code * 37 + buff[i];
        }
        return code;
    }

    // hash ignoring case
    public int hashIgnoreCase() {
        int code=0;
        for (int i = start; i < end; i++) {
            code = code * 37 + Ascii.toLower(buff[i]);
        }
        return code;
    }

    public int indexOf(char c) {
        return indexOf( c, start);
    }
    
    /**
     * Returns true if the message bytes starts with the specified string.
     * @param c the character
     */
    public int indexOf(char c, int starting) {
        int ret = indexOf( buff, start+starting, end, c );
        return (ret >= start) ? ret - start : -1;
    }

    public static int indexOf( char chars[], int off, int cend, char qq )
    {
        while( off < cend ) {
            char b=chars[off];
            if( b==qq )
                return off;
            off++;
        }
        return -1;
    }
    

    public int indexOf( String src, int srcOff, int srcLen, int myOff ) {
        char first=src.charAt( srcOff );

        // Look for first char 
        int srcEnd = srcOff + srcLen;
        
        for( int i=myOff+start; i <= (end - srcLen); i++ ) {
            if( buff[i] != first ) continue;
            // found first char, now look for a match
            int myPos=i+1;
            for( int srcPos=srcOff + 1; srcPos< srcEnd; ) {
                if( buff[myPos++] != src.charAt( srcPos++ ))
                    break;
                if( srcPos==srcEnd ) return i-start; // found it
            }
        }
        return -1;
    }

    // -------------------- utils
    private int min(int a, int b) {
        if (a < b) return a;
        return b;
    }

    // Char sequence impl
    
    public char charAt(int index) {
        return buff[index + start];
    }
    
    public CharSequence subSequence(int start, int end) {
        try {
            CharChunk result = (CharChunk) this.clone();
            result.setOffset(this.start + start);
            result.setEnd(this.start + end);
            return result;
        } catch (CloneNotSupportedException e) {
            // Cannot happen
            return null;
        }
    }
    
    public int length() {
        return end - start;
    }
    
}
