/*
 * Copyright (c) 2003 The Visigoth Software Society. All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:
 *       "This product includes software developed by the
 *        Visigoth Software Society (http://www.visigoths.org/)."
 *    Alternately, this acknowledgement may appear in the software itself,
 *    if and wherever such third-party acknowledgements normally appear.
 *
 * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the 
 *    project contributors may be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact visigoths@visigoths.org.
 *
 * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
 *    nor may "FreeMarker" or "Visigoth" appear in their names
 *    without prior written permission of the Visigoth Software Society.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Visigoth Software Society. For more
 * information on the Visigoth Software Society, please see
 * http://www.visigoths.org/
 */

package freemarker.core;

import java.io.IOException;

import freemarker.template.utility.StringUtil;

/**
 * A TemplateElement representing a block of plain text.
 */
public final class TextBlock extends TemplateElement {
    private static final char[] EMPTY_CHAR_ARRAY = new char[0];
    static final TextBlock EMPTY_BLOCK = new TextBlock(EMPTY_CHAR_ARRAY, false);
    // We're using char[] instead of String for storing the text block because
    // Writer.write(String) involves copying the String contents to a char[] 
    // using String.getChars(), and then calling Writer.write(char[]). By
    // using Writer.write(char[]) directly, we avoid array copying on each 
    // write. 
    private char[] text;
    private final boolean unparsed;

    public TextBlock(String text) {
        this(text, false);
    }

    public TextBlock(String text, boolean unparsed) {
        this(text.toCharArray(), unparsed);
    }

    private TextBlock(char[] text, boolean unparsed) {
        this.text = text;
        this.unparsed = unparsed;
    }

    /**
     * Simply outputs the text.
     */
    public void accept(Environment env) 
    throws IOException
    {
        env.getOut().write(text);
    }

    protected String dump(boolean canonical) {
        if (canonical) {
            String text = new String(this.text);
            if (unparsed) {
                return "<#noparse>" + text + "</#noparse>";
            }
            return text;
        } else {
            return "text " + StringUtil.jQuote(new String(text));
        }
    }
    
    String getNodeTypeSymbol() {
        return "#text";
    }
    
    int getParameterCount() {
        return 1;
    }

    Object getParameterValue(int idx) {
        if (idx != 0) throw new IndexOutOfBoundsException();
        return new String(text);
    }

    ParameterRole getParameterRole(int idx) {
        if (idx != 0) throw new IndexOutOfBoundsException();
        return ParameterRole.CONTENT;
    }

    TemplateElement postParseCleanup(boolean stripWhitespace) {
        if (text.length == 0) return this;
        int openingCharsToStrip = 0, trailingCharsToStrip=0;
        boolean deliberateLeftTrim = deliberateLeftTrim();
        boolean deliberateRightTrim = deliberateRightTrim();
        if (!stripWhitespace || text.length == 0 ) {
            return this;
        }
        if (parent.parent == null && previousSibling() == null) return this;
        if (!deliberateLeftTrim) {
            trailingCharsToStrip = trailingCharsToStrip();
        }
        if (!deliberateRightTrim) {
            openingCharsToStrip = openingCharsToStrip();
        }
        if (openingCharsToStrip == 0 && trailingCharsToStrip == 0) {
            return this;
        }
        this.text = substring(text, openingCharsToStrip, text.length - trailingCharsToStrip);
        if (openingCharsToStrip > 0) {
            this.beginLine++;
            this.beginColumn = 1;
        }
        if (trailingCharsToStrip >0) {
            this.endColumn = 0;
        }
        return this;
    }
    
    /**
     * Scans forward the nodes on the same line to see whether there is a 
     * deliberate left trim in effect. Returns true if the left trim was present.
     */
    private boolean deliberateLeftTrim() {
        boolean result = false;
        for (TemplateElement elem = this.nextTerminalNode(); 
             elem != null && elem.beginLine == this.endLine;
             elem = elem.nextTerminalNode()) 
        {
            if (elem instanceof TrimInstruction) {
                TrimInstruction ti = (TrimInstruction) elem;
                if (!ti.left && !ti.right) {
                    result = true;
                }
                if (ti.left) {
                    result = true;
                    int lastNewLineIndex = lastNewLineIndex();
                    if (lastNewLineIndex >=0  || beginColumn == 1) {
                        char[] firstPart = substring(text, 0, lastNewLineIndex + 1);
                        char[] lastLine = substring(text, 1+lastNewLineIndex); 
                        if (trim(lastLine).length == 0) {
                            this.text = firstPart;
                            this.endColumn = 0;
                        } else {
                            int i =0;
                            while (Character.isWhitespace(lastLine[i])) {
                                i++;
                            }
                            char[] printablePart = substring(lastLine, i);
                            this.text = concat(firstPart, printablePart);
                        }
                    }
                }
            }
        }
        if (result) {
        }
        return result;
    }

    /**
     * Checks for the presence of a t or rt directive on the 
     * same line. Returns true if the right trim directive was present.
     */
    private boolean deliberateRightTrim() {
        boolean result = false;
        for (TemplateElement elem = this.prevTerminalNode(); 
             elem != null && elem.endLine == this.beginLine;
             elem = elem.prevTerminalNode())
        {
            if (elem instanceof TrimInstruction) {
                TrimInstruction ti = (TrimInstruction) elem;
                if (!ti.left && !ti.right) {
                    result = true;
                }
                if (ti.right) {
                    result = true;
                    int firstLineIndex = firstNewLineIndex() +1;
                    if (firstLineIndex == 0) {
                        return false;
                    }
                    if (text.length > firstLineIndex 
                        && text[firstLineIndex-1] == '\r' 
                        && text[firstLineIndex] == '\n') 
                    {
                        firstLineIndex++;
                    }
                    char[] trailingPart = substring(text, firstLineIndex);
                    char[] openingPart = substring(text, 0, firstLineIndex);
                    if (trim(openingPart).length ==0) {
                        this.text = trailingPart;
                        this.beginLine++;
                        this.beginColumn=1;
                    } else {
                        int lastNonWS = openingPart.length -1;
                        while (Character.isWhitespace(text[lastNonWS])) {
                            lastNonWS--;
                        }
                        char[] printablePart = substring(text, 0, lastNonWS+1);
                        if (trim(trailingPart).length == 0) {
                        // THIS BLOCK IS HEINOUS! THERE MUST BE A BETTER WAY! REVISIT (JR)
                            boolean trimTrailingPart = true;
                            for (TemplateElement te = this.nextTerminalNode(); 
                                 te != null && te.beginLine == this.endLine;
                                 te = te.nextTerminalNode()) 
                            {
                                if (te.heedsOpeningWhitespace()) 
                                {
                                    trimTrailingPart = false;
                                }
                                if (te instanceof TrimInstruction && ((TrimInstruction) te).left) {
                                    trimTrailingPart = true;
                                    break;
                                }
                            }
                            if (trimTrailingPart) trailingPart = EMPTY_CHAR_ARRAY;
                        }
                        this.text = concat(printablePart, trailingPart);
                    }
                }
            }
        }
        return result;
    }
/*
    private String leftTrim(String s) {
        int i =0;
        while (i<s.length()) {
            if (!Character.isWhitespace(s.charAt(i)))
                break;
            ++i;
        }
        return s.substring(i);
    }
*/
    private int firstNewLineIndex() {
        String content = new String(text);
        int newlineIndex1 = content.indexOf('\n');
        int newlineIndex2 = content.indexOf('\r');
        int result = newlineIndex1 >=0 ? newlineIndex1 : newlineIndex2;
        if (newlineIndex1 >=0 && newlineIndex2 >=0) {
            result = Math.min(newlineIndex1, newlineIndex2);
        }
        return result;
    }

    private int lastNewLineIndex() {
        String content = new String(text);
        return Math.max(content.lastIndexOf('\r'), content.lastIndexOf('\n'));
    }

    /**
     * figures out how many opening whitespace characters to strip
     * in the post-parse cleanup phase.
     */
    private int openingCharsToStrip() {
        int newlineIndex = firstNewLineIndex();
        if (newlineIndex == -1 && beginColumn != 1) {
            return 0;
        }
        ++newlineIndex;
        if (text.length > newlineIndex) {
            if (newlineIndex >0 && text[newlineIndex-1] == '\r' && text[newlineIndex] == '\n') {
                ++newlineIndex;
            }
        }
        if (new String(text).substring(0, newlineIndex).trim().length() >0) {
            return 0;
        }
// We look at the preceding elements on the line to see if we should
// strip the opening newline and any whitespace preceding it.
        for (TemplateElement elem = this.prevTerminalNode(); 
             elem != null && elem.endLine == this.beginLine;
             elem = elem.prevTerminalNode())
        {
            if (elem.heedsOpeningWhitespace())
            {
                return 0;
            }
        }
        return newlineIndex;
    }

    /**
     * figures out how many trailing whitespace characters to strip
     * in the post-parse cleanup phase.
     */
    private int trailingCharsToStrip() {
        String content = new String(text);
        int lastNewlineIndex = lastNewLineIndex();
        if (lastNewlineIndex == -1 && beginColumn != 1) {
            return 0;
        }
        String substring = content.substring(lastNewlineIndex +1);
        if (substring.trim().length() >0) {
            return 0;
        }
// We look at the elements afterward on the same line to see if we should
// strip any whitespace after the last newline
        for (TemplateElement elem = this.nextTerminalNode(); 
             elem != null && elem.beginLine == this.endLine;
             elem = elem.nextTerminalNode()) 
        {
            if (elem.heedsTrailingWhitespace()) 
            {
                return 0;
            }
        }
        return substring.length();
    }

    boolean heedsTrailingWhitespace() {
        if (isIgnorable()) {
            return false;
        }
        for (int i=0; i<text.length; i++) {
            char c = text[i];
            if (c=='\n' || c=='\r') {
                return false;
            }
            if (!Character.isWhitespace(c)) {
                return true;
            }
        }
        return true;
    }

    boolean heedsOpeningWhitespace() {
        if (isIgnorable()) {
            return false;
        }
        for (int i = text.length -1; i>=0; i--) {
            char c = text[i];
            if (c == '\n' || c == '\r') {
                return false;
            }
            if (!Character.isWhitespace(c)) {
                return true;
            }
        }
        return true;
    }

    boolean isIgnorable() {
        if (text == null || text.length == 0) {
            return true;
        }
        if (!isWhitespace()) {
            return false;
        }
        boolean atTopLevel = (getParent().getParent() == null);
        TemplateElement prevSibling = previousSibling();
        TemplateElement nextSibling = nextSibling();
        return ((prevSibling == null && atTopLevel) || nonOutputtingType(prevSibling))
              && ((nextSibling == null && atTopLevel) || nonOutputtingType(nextSibling));
    }
    

    private boolean nonOutputtingType(TemplateElement element) {
        return (element instanceof Macro ||
                element instanceof Assignment || 
                element instanceof AssignmentInstruction ||
                element instanceof PropertySetting ||
                element instanceof LibraryLoad ||
                element instanceof Comment);
    }

    private static char[] substring(char[] c, int from, int to) {
        char[] c2 = new char[to - from];
        System.arraycopy(c, from, c2, 0, c2.length);
        return c2;
    }
    
    private static char[] substring(char[] c, int from) {
        return substring(c, from, c.length);
    }
    
    private static char[] trim(char[] c) {
        if (c.length == 0) {
            return c;
        }
        return new String(c).trim().toCharArray();
    }
    
    private static char[] concat(char[] c1, char[] c2) {
        char[] c = new char[c1.length + c2.length];
        System.arraycopy(c1, 0, c, 0, c1.length);
        System.arraycopy(c2, 0, c, c1.length, c2.length);
        return c;
    }
    
    boolean isWhitespace() {
        return text == null || trim(text).length == 0;
    }
}
