/**
 * 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.
 */

/*
 * "Line.java"
 * Line.java 1.12 01/07/24
 */

package org.netbeans.lib.terminalemulator;

final class Line {
    public int glyph_glyph;
    public int glyph_rendition;	// Background color for the whole line
    				// This is independent of per-character
				// rendition.

    private char buf[];		// actual characters
    private int attr[];		// attributes (allocated on demand)
    
    // SHOULD use shorts?
    private int capacity;	// == buf.length == attr.length
    private int length;		// how much of buf and attr is filled
    
    
    public Line() {
        reset();
    }
    
    public void reset() {
        length = 0;
        capacity = 32;
        buf = new char[capacity];
        attr = null;
        glyphId = 0;
        backgroundColor = 0;
        wrapped = false;
        about_to_wrap = false;
    }

    public void reset(Term term, int end, int eraseAttr) {
        reset();
        clearToEndFrom(term, 0, end, eraseAttr);
    }
    
    public int capacity() {
        return capacity;
    }
    
    /**
     * Number of characters in the line.
     * charArray()[length()] is where the cursor or newline would be.
     *
     */
    public int length() {
        return length;
    }
    
    public boolean hasAttributes() {
        return attr != null;
    }
    
    private int glyphId;
    public void setGlyphId(int glyphId) {
        this.glyphId = glyphId;
    }
    public int getGlyphId() {
        return glyphId;
    }
    
    private int backgroundColor;// Background color for the whole line
    // This is independent of per-character
    // rendition.
    public void setBackgroundColor(int bgColor) {
        backgroundColor = bgColor;
    }
    public int getBackgroundColor() {
        return backgroundColor;
    }
    
    public void setWrapped(boolean wrapped) {
        this.wrapped = wrapped;
    }
    public boolean isWrapped() {
        return wrapped;
    }
    // SHOULD collapse wrapped with about_to_wrap into a bitfield
    private boolean wrapped;
    
    
    
    public boolean setAboutToWrap(boolean about_to_wrap) {
        boolean old_about_to_wrap = about_to_wrap;
        this.about_to_wrap = about_to_wrap;
        return old_about_to_wrap;
    }
    public boolean isAboutToWrap() {
        return about_to_wrap;
    }
    // Perhaps SHOULD have a state: normal, about-to-wrap, wrapped.
    private boolean about_to_wrap;
    
    
    /**
     * Return true if we've already seen attributes for this line
     * or 'a' is the first one, in which case we allocate the 'attr' array.
     */
    private boolean haveAttributes(int a) {
        if (attr == null && a != 0) {
            attr = new int[capacity];
        }
        return attr != null;
    }
    
    
    public void accumulateInto(int bcol, int ecol, StringBuffer buf) {
        buf.append(this.buf, bcol, ecol-bcol+1);
    }
    
    public char charAt(int col) {
        return buf[col];
    }
    
    private void charAtPut(int col, char c) {
        buf[col] = c;
    }
    
    @Override
    public String toString() {
        assert false;
        return new String(buf);
    }
    
    public char[] getChars(char[] array) {
        System.arraycopy(buf, 0, array, 0, length);
        return array;
    }
    
    public int [] attrArray() {
        return attr;
    }
    
    
    public byte width(MyFontMetrics metrics, int at) {
        if (at >= capacity)
            return 1;
        return (byte) metrics.wcwidth(charAt(at));
    }
    
    /*
     * Convert a cell column to a buffer column.
     */
    public int cellToBuf(MyFontMetrics metrics, int target_col) {
        if (metrics.isMultiCell()) {
            int bc = 0;
            int vc = 0;
            for(;;) {
                int w = width(metrics, bc);
                if (vc + w - 1 >= target_col)
                    break;
                vc += w;
                bc++;
            }
            return bc;
        } else {
            return target_col;
        }
    }
    
    /*
     * Convert a buffer column to a cell column.
     */
    public int bufToCell(MyFontMetrics metrics, int target_col) {
        if (metrics.isMultiCell()) {
            int vc = 0;
            for (int bc = 0; bc < target_col; bc++) {
                vc += width(metrics, bc);
            }
            return vc;
        } else {
            return target_col;
        }
    }
    
    
    
    public StringBuffer stringBuffer() {
        // only used for word finding
        // Grrr, why don't we have: new StringBuffer(buf, 0, length);

        // This gets passed on to WordDelineator which is part of the public API
        @SuppressWarnings("StringBufferMayBeStringBuilder")

        StringBuffer sb = new StringBuffer(length);
        return sb.append(buf, 0, length);
    }
    
    /*
     * Ensure that we have at least 'min_capacity'.
     */
    private void ensureCapacity(Term term, int min_capacity) {
        
        term.noteColumn(this, min_capacity);
        
        if (min_capacity <= capacity)
            return;	// nothing to do
        
        // doubling
        int new_capacity = (length+1) * 2;
        if (new_capacity < 0)
            new_capacity = Integer.MAX_VALUE;
        else if (min_capacity > new_capacity)
            new_capacity = min_capacity;
        
        
        char new_buf[] = new char[new_capacity];
        System.arraycopy(buf, 0, new_buf, 0, length);
        buf = new_buf;
        
        if (attr != null) {
            int new_attr[] = new int[new_capacity];
            System.arraycopy(attr, 0, new_attr, 0, length);
            attr = new_attr;
        }
        
        capacity = new_capacity;
    }

    private void fillGap(int col, int eraseAttr) {
        // fill any newly opened gap (between length and col) with SP
        for (int cx = length; cx < col; cx++)
            charAtPut(cx, ' ');
        if (haveAttributes(eraseAttr)) {
            for (int cx = length; cx < col; cx++)
                attr[col] = eraseAttr;
        }
    }
    
    /**
     * Insert character and attribute at 'column' and shift everything
     * past 'column' right.
     */
    public void insertCharAt(Term term, char c, int column, int a) {
        int new_length = length + 1;
        
        if (column >= length) {
            new_length = column+1;
            ensureCapacity(term, new_length);
            fillGap(column, 0);                 // SHOULD be eraseAttr?
        } else {
            ensureCapacity(term, new_length);
            System.arraycopy(buf, column, buf, column + 1, length - column);
            if (haveAttributes(a))
                System.arraycopy(attr, column, attr, column + 1, length - column);
        }
        
        term.checkForMultiCell(c);
        
        charAtPut(column, c);
        if (haveAttributes(a))
            attr[column] = a;
        
        length = new_length;
    }
    
    /*
     * Generic addition and modification.
     * Line will grow to accomodate column.
     */
    public void setCharAt(Term term, char c, int column, int a, int eraseAttr) {
        if (column >= length) {
            ensureCapacity(term, column+1);
            fillGap(column, eraseAttr);
            length = column+1;
        }
        term.checkForMultiCell(c);
        if (column < 0) {
            throw new IllegalArgumentException(String.format("column=%d; buf_length=%d; buf_capacity=%d", column, length, capacity));   //NOI18N
        }
        charAtPut(column, c);
        if (haveAttributes(a)) {
            attr[column] = a;
        }
    }
    
    public void deleteCharAt(int column) {
        if (column < 0 || column >= length)
            return;
        System.arraycopy(buf, column+1, buf, column, length-column-1);
        charAtPut(length-1, (char) 0);
        if (attr != null) {
            System.arraycopy(attr, column+1, attr, column, length-column-1);
            attr[length-1] = 0;
        }
        // SHOULD move this up
        length--;
    }
    
    public void clearToEndFrom(Term term, int from, int end, int eraseAttr) {
        ensureCapacity(term, end+1);
        fillGap(end, eraseAttr);

        // Grrr, why is there a System.arrayCopy() but no System.arrayClear()?
        for (int cx = from; cx <= end; cx++)
            charAtPut(cx, ' ');
        if (haveAttributes(eraseAttr)) {
            for (int cx = from; cx <= end; cx++)
                attr[cx] = eraseAttr;
        }
        length = end+1;
    }

    public void clearTo(Term term, int col, int eraseAttr) {
        ensureCapacity(term, col+1);
        fillGap(col, eraseAttr);

        for (int cx = 0; cx <= col; cx++)
            charAtPut(cx, ' ');
        if (haveAttributes(eraseAttr)) {
            for (int cx = 0; cx <= col; cx++)
                attr[cx] = eraseAttr;
        }
        if (length < col+1)
            length = col+1;
    }

    public void clearFromTo(Term term, int from, int to, int eraseAttr) {
        if (from > to)
            return;
        ensureCapacity(term, to+1);
        fillGap(to, eraseAttr);

        for (int cx = from; cx <= to; cx++)
            charAtPut(cx, ' ');
        if (haveAttributes(eraseAttr)) {
            for (int cx = from; cx <= to; cx++)
                attr[cx] = eraseAttr;
        }
        if (length < to+1)
            length = to+1;
    }
    
    /*
     * Used for selections
     * If the ecol is past the actual line length a "\n" is appended.
     */
    @SuppressWarnings("AssignmentToMethodParameter")
    public String text(int bcol, int ecol) {
        /* DEBUG
        System.out.println("Line.text(bcol " + bcol + " ecol " + ecol + ")");	// NOI18N
        System.out.println("\tlength " + length);	// NOI18N
         */
        
        
        String newline = "";	// NOI18N
        
        // This only happens for 'empty' lines below the cursor.
        // Actually it also happens for 'empty' lines in the middle.
        // See issue 31951 for example.
        // So in order to get newlines in selected text we will also get
        // newlines from the 'empty' lines below the cursor.
        // This is in fact what xterm does.
        // DtTerm doesn't allow selection of the 'empty' lines below the
        // cursor, but that is issue 21577 and is not easy to solve.
        
        if (length == 0)
	    return "\n"; // NOI18N
        
        if (ecol >= length) {
            // The -1 snuffs out the newline.
            ecol = length-1;
            newline = "\n";	// NOI18N
            
            if (bcol >= length)
                bcol = length-1;
        }
        int count = ecol - bcol + 1;
        if (bcol < 0 ||  count < 0) {
            throw new IllegalArgumentException(String.format("offset=%d; count=%d; buf_length=%d; buf_capacity=%d", bcol, count, length, capacity));    //NOI18N
        }
        return new String(buf, bcol, count) + newline;
    }
    
    public void setCharacterAttribute(int bcol, int ecol,
            int value, boolean on) {
        // HACK: value is the ANSI code, haveAttributes takes out own
        // compact encoding, but it only checks for 0 so it's OK.
        if (!haveAttributes(value))
            return;
        
	try {
	    if (on) {
		for (int c = bcol; c <= ecol; c++)
		    attr[c] = Attr.setAttribute(attr[c], value);
	    } else {
		for (int c = bcol; c <= ecol; c++)
		    attr[c] = Attr.unsetAttribute(attr[c], value);
	    }
	} catch (ArrayIndexOutOfBoundsException x) {
	    System.out.printf("bcol %d  ecol %d  capacity %d  length %d buf %d  attr %d", // NOI18N
		    bcol, ecol, capacity, length, buf.length, attr.length);
	    throw x;
	}
    }
}
