package org.apache.http.util;

import org.apache.http.protocol.HTTP;
import java.io.Serializable;
import java.nio.CharBuffer;

public final class CharArrayBuffer implements CharSequence, Serializable {
   private static final long serialVersionUID = -6208952725094867135L;
   private char[] buffer;
   private int len;

   public CharArrayBuffer(int capacity) {
      Args.notNegative(capacity, "Buffer capacity");
      this.buffer = new char[capacity];
   }

   private void expand(int newlen) {
      char[] newbuffer = new char[Math.max(this.buffer.length << 1, newlen)];
      System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
      this.buffer = newbuffer;
   }

   public void append(char[] b, int off, int len) {
      if (b != null) {
         if (off >= 0 && off <= b.length && len >= 0 && off + len >= 0 && off + len <= b.length) {
            if (len != 0) {
               int newlen = this.len + len;
               if (newlen > this.buffer.length) {
                  this.expand(newlen);
               }

               System.arraycopy(b, off, this.buffer, this.len, len);
               this.len = newlen;
            }
         } else {
            throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
         }
      }
   }

   public void append(String str) {
      String s = str != null ? str : "null";
      int strlen = s.length();
      int newlen = this.len + strlen;
      if (newlen > this.buffer.length) {
         this.expand(newlen);
      }

      s.getChars(0, strlen, this.buffer, this.len);
      this.len = newlen;
   }

   public void append(CharArrayBuffer b, int off, int len) {
      if (b != null) {
         this.append(b.buffer, off, len);
      }
   }

   public void append(CharArrayBuffer b) {
      if (b != null) {
         this.append((char[])b.buffer, 0, b.len);
      }
   }

   public void append(char ch) {
      int newlen = this.len + 1;
      if (newlen > this.buffer.length) {
         this.expand(newlen);
      }

      this.buffer[this.len] = ch;
      this.len = newlen;
   }

   public void append(byte[] b, int off, int len) {
      if (b != null) {
         if (off >= 0 && off <= b.length && len >= 0 && off + len >= 0 && off + len <= b.length) {
            if (len != 0) {
               int oldlen = this.len;
               int newlen = oldlen + len;
               if (newlen > this.buffer.length) {
                  this.expand(newlen);
               }

               int i1 = off;

               for(int i2 = oldlen; i2 < newlen; ++i2) {
                  this.buffer[i2] = (char)(b[i1] & 255);
                  ++i1;
               }

               this.len = newlen;
            }
         } else {
            throw new IndexOutOfBoundsException("off: " + off + " len: " + len + " b.length: " + b.length);
         }
      }
   }

   public void append(ByteArrayBuffer b, int off, int len) {
      if (b != null) {
         this.append(b.buffer(), off, len);
      }
   }

   public void append(Object obj) {
      this.append(String.valueOf(obj));
   }

   public void clear() {
      this.len = 0;
   }

   public char[] toCharArray() {
      char[] b = new char[this.len];
      if (this.len > 0) {
         System.arraycopy(this.buffer, 0, b, 0, this.len);
      }

      return b;
   }

   public char charAt(int i) {
      return this.buffer[i];
   }

   public char[] buffer() {
      return this.buffer;
   }

   public int capacity() {
      return this.buffer.length;
   }

   public int length() {
      return this.len;
   }

   public void ensureCapacity(int required) {
      if (required > 0) {
         int available = this.buffer.length - this.len;
         if (required > available) {
            this.expand(this.len + required);
         }

      }
   }

   public void setLength(int len) {
      if (len >= 0 && len <= this.buffer.length) {
         this.len = len;
      } else {
         throw new IndexOutOfBoundsException("len: " + len + " < 0 or > buffer len: " + this.buffer.length);
      }
   }

   public boolean isEmpty() {
      return this.len == 0;
   }

   public boolean isFull() {
      return this.len == this.buffer.length;
   }

   public int indexOf(int ch, int from, int to) {
      int beginIndex = from;
      if (from < 0) {
         beginIndex = 0;
      }

      int endIndex = to;
      if (to > this.len) {
         endIndex = this.len;
      }

      if (beginIndex > endIndex) {
         return -1;
      } else {
         for(int i = beginIndex; i < endIndex; ++i) {
            if (this.buffer[i] == ch) {
               return i;
            }
         }

         return -1;
      }
   }

   public int indexOf(int ch) {
      return this.indexOf(ch, 0, this.len);
   }

   public String substring(int beginIndex, int endIndex) {
      if (beginIndex < 0) {
         throw new IndexOutOfBoundsException("Negative beginIndex: " + beginIndex);
      } else if (endIndex > this.len) {
         throw new IndexOutOfBoundsException("endIndex: " + endIndex + " > length: " + this.len);
      } else if (beginIndex > endIndex) {
         throw new IndexOutOfBoundsException("beginIndex: " + beginIndex + " > endIndex: " + endIndex);
      } else {
         return new String(this.buffer, beginIndex, endIndex - beginIndex);
      }
   }

   public String substringTrimmed(int beginIndex, int endIndex) {
      if (beginIndex < 0) {
         throw new IndexOutOfBoundsException("Negative beginIndex: " + beginIndex);
      } else if (endIndex > this.len) {
         throw new IndexOutOfBoundsException("endIndex: " + endIndex + " > length: " + this.len);
      } else if (beginIndex > endIndex) {
         throw new IndexOutOfBoundsException("beginIndex: " + beginIndex + " > endIndex: " + endIndex);
      } else {
         int beginIndex0 = beginIndex;

         int endIndex0;
         for(endIndex0 = endIndex; beginIndex0 < endIndex && HTTP.isWhitespace(this.buffer[beginIndex0]); ++beginIndex0) {
         }

         while(endIndex0 > beginIndex0 && HTTP.isWhitespace(this.buffer[endIndex0 - 1])) {
            --endIndex0;
         }

         return new String(this.buffer, beginIndex0, endIndex0 - beginIndex0);
      }
   }

   public CharSequence subSequence(int beginIndex, int endIndex) {
      if (beginIndex < 0) {
         throw new IndexOutOfBoundsException("Negative beginIndex: " + beginIndex);
      } else if (endIndex > this.len) {
         throw new IndexOutOfBoundsException("endIndex: " + endIndex + " > length: " + this.len);
      } else if (beginIndex > endIndex) {
         throw new IndexOutOfBoundsException("beginIndex: " + beginIndex + " > endIndex: " + endIndex);
      } else {
         return CharBuffer.wrap(this.buffer, beginIndex, endIndex);
      }
   }

   public String toString() {
      return new String(this.buffer, 0, this.len);
   }
}
