package com.wizzardo.epoll.readable;

import java.nio.ByteBuffer;

/**
 * @author: wizzardo
 * Date: 7/25/14
 */
public class ReadableBuilder extends ReadableData {
    private ReadableByteArray[] parts = new ReadableByteArray[20];
    private int partsCount = 0;
    private int position = 0;

    public ReadableBuilder() {
    }

    public ReadableBuilder(byte[] bytes) {
        this(bytes, 0, bytes.length);
    }

    public ReadableBuilder(byte[] bytes, int offset, int length) {
        partsCount = 1;
        parts[0] = new ReadableByteArray(bytes, offset, length);
    }

    public ReadableBuilder append(byte[] bytes) {
        return append(bytes, 0, bytes.length);
    }

    public ReadableBuilder append(byte[] bytes, int offset, int length) {
        if (partsCount + 1 == parts.length)
            increaseSize();

        parts[partsCount] = new ReadableByteArray(bytes, offset, length);
        partsCount++;

        return this;
    }

    private void increaseSize() {
        ReadableByteArray[] temp = new ReadableByteArray[partsCount * 3 / 2];
        System.arraycopy(parts, 0, temp, 0, partsCount);
        parts = temp;
    }

    @Override
    public int read(ByteBuffer byteBuffer) {
        if (position >= partsCount)
            return 0;

        int r = parts[position].read(byteBuffer);
        while (position < partsCount - 1 && parts[position].isComplete() && byteBuffer.hasRemaining()) {
            r += parts[++position].read(byteBuffer);
        }

        return r;
    }

    @Override
    public void unread(int i) {
        while (i > 0) {
            ReadableByteArray part = parts[position];
            int unread = (int) Math.min(i, part.complete());
            parts[position].unread(unread);
            i -= unread;
            if (i > 0)
                position--;
        }
    }

    @Override
    public boolean isComplete() {
        return position == partsCount - 1 && parts[position].isComplete();
    }

    @Override
    public long complete() {
        long l = 0;
        for (int i = 0; i <= position; i++) {
            ReadableByteArray part = parts[i];
            if (parts[i].isComplete())
                l += parts[i].length();
            else
                l += part.complete();
        }
        return l;
    }

    @Override
    public long length() {
        long l = 0;
        for (int i = 0; i < partsCount; i++) {
            l += parts[i].length();
        }
        return l;
    }

    @Override
    public long remains() {
        long l = 0;
        for (int i = partsCount - 1; i >= 0; i--) {
            if (parts[i].isComplete())
                break;
            l += parts[i].remains();
        }
        return l;
    }

    public ReadableByteArray toReadableByteArray() {
        byte[] data = new byte[(int) length()];
        int offset = 0;
        for (int i = 0; i < partsCount; i++) {
            ReadableByteArray part = parts[i];
            System.arraycopy(part.bytes, part.offset, data, offset, part.length);
            offset += part.length;
        }
        return new ReadableByteArray(data);
    }
}

@@ -178,25 +178,20 @@
 Readable
-ByteArray
+Data
 %5B%5D parts
@@ -205,25 +205,20 @@
 Readable
-ByteArray
+Data
 %5B20%5D;%0A  
@@ -939,24 +939,253 @@
 his;%0A    %7D%0A%0A
+    public ReadableBuilder append(ReadableData readableData) %7B%0A        if (partsCount + 1 == parts.length)%0A            increaseSize();%0A%0A        parts%5BpartsCount%5D = readableData;%0A        partsCount++;%0A%0A        return this;%0A    %7D%0A%0A
     private 
@@ -1222,25 +1222,20 @@
 Readable
-ByteArray
+Data
 %5B%5D temp 
@@ -1248,25 +1248,20 @@
 Readable
-ByteArray
+Data
 %5BpartsCo
@@ -1808,33 +1808,28 @@
     Readable
-ByteArray
+Data
  part = part
@@ -2294,33 +2294,28 @@
     Readable
-ByteArray
+Data
  part = part
@@ -2908,32 +2908,34 @@
 eturn l;%0A    %7D%0A%0A
+//
     public Reada
@@ -2967,24 +2967,26 @@
 teArray() %7B%0A
+//
         byte
@@ -3021,16 +3021,18 @@
 gth()%5D;%0A
+//
         
@@ -3043,24 +3043,26 @@
 offset = 0;%0A
+//
         for 
@@ -3088,32 +3088,34 @@
 tsCount; i++) %7B%0A
+//
             Read
@@ -3118,25 +3118,20 @@
 Readable
-ByteArray
+Data
  part = 
@@ -3132,32 +3132,34 @@
 art = parts%5Bi%5D;%0A
+//
             Syst
@@ -3216,32 +3216,34 @@
 , part.length);%0A
+//
             offs
@@ -3261,16 +3261,18 @@
 length;%0A
+//
         
@@ -3265,32 +3265,34 @@
 th;%0A//        %7D%0A
+//
         return n
@@ -3319,16 +3319,18 @@
 (data);%0A
+//
     %7D%0A%7D%0A

improve builder