package cnp.ew.richtext;

import java.awt.*;
import java.util.*;

public class CpTextModel
{
    static final int chunkSize = 20;

    private int numChars;
    private int maxNumChars;
    private char[] chars;

    public CpTextModel(String string)
    {
	    this(string.toCharArray());
    }

    public CpTextModel(char[] chars, int offset, int length)
    {
	    char[] newChars = new char[length];
        System.arraycopy(chars, offset, newChars, 0, length);
	    initialize(newChars);
    }

    public CpTextModel getCopy()
    {
        return new CpTextModel(chars, 0, numChars);
    }


    public CpTextModel(char[] chars)
    {
	    initialize(chars);
    }

    public String toString()
    {
        return "NumChars: " + numChars + ", maxNumChars: " + maxNumChars + ", chars: " + chars;
    }

    public String getString()
    {
        return new String(chars, 0, numChars);
    }

    private void initialize(char[] newChars)
    {
    	numChars = newChars.length;
    	maxNumChars = getMaxSize(numChars);
    	chars = new char[maxNumChars];
    	System.arraycopy(newChars, 0, this.chars, 0, numChars);
    }

    public char[] getChars()
    {
    	char[] newChars = new char[numChars];
    	System.arraycopy(this.chars, 0, newChars, 0, numChars);
        return newChars;
    }

    private void growTo(int size)
    {
    	if (maxNumChars <= size) {
    	    char oldChars[] = chars;
    	    maxNumChars = getMaxSize(size);
    	    chars = new char[maxNumChars];
    	    System.arraycopy(oldChars, 0, chars, 0, numChars);
    	}
    }

    private int getMaxSize(int size)
    {
        return (size / chunkSize + 1) * chunkSize;
    }


    private int deleteSpace(char array[], int numChars, int index, int num)
    {
	    int end = numChars - num;

    	for (int i = index; i < end; i++) {
    	    array[i] = array[i + num];
    	}

    	return numChars - num;
    }

    private int createSpace(char array[], int numChars, int index, int num)
    {
    	int end = numChars + num;

    	for (int i = end - 1; i >= index + num; i--) {
    	    array[i] = array[i - num];
    	}

    	return end;
    }


    public int length()
    {
    	return numChars;
    }

    public char charAt(int offset)
    {
    	if (numChars <= offset)	{
    	    throw new IndexOutOfBoundsException();
    	}

    	return chars[offset];
    }

    public void append(char c)
    {
	    char[] tempChars = new char[1];
	    tempChars[0] = c;
    	append(tempChars);
    }

    public void append(char[] tempChars)
    {
	    growTo(numChars + tempChars.length);
	    System.arraycopy(tempChars, 0, chars, numChars, tempChars.length);
	    numChars += tempChars.length;
    }

    public void insert(int offset, char ch)
    {
	    char[] tempChars = new char[1];
	    tempChars[0] = ch;
    	insert(offset, tempChars);
    }

    public void insert(int offset, char[] tempChars)
    {
	    growTo(numChars + tempChars.length);
	    numChars = createSpace(chars, numChars, offset, tempChars.length);
	    System.arraycopy(tempChars, 0, chars, offset, tempChars.length);
    }

    public void delete(int offset, int length)
    {
	    numChars = deleteSpace(chars, numChars, offset, length);
    }

    public Point getWordAtOffset(int offset)
    {
        // Currently breaks on spaces and char 0 (an image)

        int start = offset;
        while (start > 0) {
            if (charAt(start) == ' ' || charAt(start) == (char)0) {
                start = Math.min(offset, start + 1);
                break;
            }
            start--;
        }
        int end = offset;
        while (end < length()) {
            if (charAt(end) == ' ' || charAt(end) == (char)0) {
                break;
            }
            end++;
        }
        return new Point(start, end);
    }

    int skipSpaces(int offset)
    {
        int curOffset = offset;
        while (curOffset < length()) {
            if (charAt(curOffset) != ' ') {
                return curOffset;
            }
            curOffset++;
        }
        return length();
    }


    public int getToken(int offset, Vector tokens)
    {
        int curOffset = skipSpaces(offset);
    //    System.out.println("  After skip spaces, offset = " + curOffset);
        int start = curOffset;
        while (curOffset < length()) {
            char c = charAt(curOffset);
            if (c == ' ') {
                break;
            }
            if (c == ';' || c == '"' || c == '(' || c == ')' || c == '}' || c == '{' || c == '=' || c == '+' || c == '-' || c == '.' || c == ']' || c == '[' || c == ',') {
                if (curOffset == start) { // the run is just this token
                    curOffset++;
                }
                break;
            }
            if (c == '/') {
                if (curOffset > start) {
                    break;
                }
                curOffset++;
                c = charAt(curOffset);
                if (c == '/' || c == '*') {
                    curOffset++;
                }
                break;  // If // then return //, if just / return that as a token
            }
            if (c == '*') {
                if (curOffset > start) {
                    break;
                }
                curOffset++;
                if (charAt(curOffset) == '/') {
                    curOffset++;
                }
                break;  // If // then return //, if just / return that as a token
            }
            curOffset++;
        }
   //     System.out.println("  Adding token: " + new String(chars, start, curOffset - start) + ", offset = " + curOffset + " len = " + (curOffset - start));
        if (curOffset != start) {
            tokens.addElement(new CpRun(start, curOffset - start, new String(chars, start, curOffset - start)));
        }
        return curOffset;
    }
}

