package jp.sourceforge.projects.ee2e.core.editors;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;

import jp.sourceforge.projects.ee2e.core.EE2EDebug;
import jp.sourceforge.projects.ee2e.core.relax.*;
import jp.sourceforge.projects.ee2e.core.lispedit.LispScanner;

/**
 * To change this generated comment edit the template variable "typecomment":
 * Window&gt;Preferences&gt;Java&gt;Templates.
 * To enable and disable the creation of type comments go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation.
 *
 * @author Toshikazu Ando [ ando@park.ruru.ne.jp ]
 */
public class EE2EIndentLisp extends EE2EIndentBehavior {
    /** constractor */
    public EE2EIndentLisp() {
    }

    /**
     * @see jp.sourceforge.projects.ee2e.core.editors.EE2EMenuBehavior#tabDestroyer(AbstractTextEditor, IDocument, ITextSelection)
     */
    protected void doIndent(int argumentOffset, IDocument document)
        throws BadLocationException {

        int len = getLispCalculateIndent(argumentOffset, document);
        EE2ELispBase.get().indentTo(argumentOffset, len, document);
    }
    protected int getLispCalculateIndent(int argumentOffset, IDocument document)
        throws BadLocationException {
        int offset =
            EE2ELispBase.get().beginningOfLine(argumentOffset, document);
        if (offset <= 0) {
            EE2ELispBase.get().indentTo(offset, 0, document);
            return 0;
        }
        if(this.doSharpSheck(offset,document)) {
            return 0;
        }
        boolean toriger = false;
        if (this.isNowTroiger(offset, document)) {
            return 0;
        }
        int pos = 0;
        for (offset--; 0 <= offset; offset--) {
            if (this.isQuoteToriger(offset, document)) {
                toriger = !toriger;
            }
            if (toriger) {
                continue;
            }
            if (this.isComment(offset, document)) {
                continue;
            }
            char ch = document.getChar(offset);
            if (ch == '(') {
                pos--;
                if (pos < 0) {
                    break;
                }
            } else if (ch == ')') {
                pos++;
            }
        }
        if (0 <= pos) {
            return 0;
        }
        offset++;
        if (this.isDefine(offset, document)) {
            offset++;
        } else {
            int oldOffset = offset;
            for (; offset < document.getLength(); offset++) {
                char ch = document.getChar(offset);
                if ((ch == '\r')
                    || (ch == '\n')
                    || (ch == ' ')
                    || (ch == '\t')
                    || (ch == ';')) {
                    break;
                }
            }
            int counter = 0;
            for (; offset < document.getLength(); offset++) {
                char ch = document.getChar(offset);
                if ((ch != ' ') && (ch != '\t')) {
                    break;
                }
                counter++;
            }
            if ((counter == 0) || (document.getLength() <= offset)) {
                offset = oldOffset;
            } else {
                char ch = document.getChar(offset);
                if ((ch == '\r') || (ch == '\t') || (ch == ';')) {
                    offset = oldOffset;
                }
            }
        }
        for (pos = offset - 1; 0 <= pos; pos--) {
            char ch = document.getChar(pos);
            if ((ch == '\r') || (ch == '\n')) {
                break;
            }
        }
        pos++;
        return offset - pos;
    }

    /**     */
    protected boolean isDefine(int offset, IDocument document)
        throws BadLocationException {
        EE2REe2e ee2e = EE2EToolkit.get().getEe2e(LispScanner.TARGET);
        if (ee2e == null) {
            EE2EDebug.printf(1, "getDefvarData/ee2e is null");
            return false;
        }
        EE2RDefvar defvar = EE2EToolkit.get().getDefvar(LispScanner.CONSTANTS);
        if (defvar == null) {
            EE2EDebug.printf(1, "getDefvarData/defvar is null");
            return false;
        }
        for (int i = 0; i < defvar.getContentCount(); i++) {
            IEE2RDefvarChoice choice = defvar.getContent(i);
            if (!(choice instanceof EE2RTag)) {
                continue;
            }
            EE2RTag tag = (EE2RTag) choice;
            if (EE2ELispBase
                .get()
                .lookingAt(offset, tag.getName(), document)) {
                return true;
            }
        }
        return false;
    }

    /**     */
    protected boolean isComment(int offset, IDocument document)
        throws BadLocationException {
        boolean toriger = false;
        for (int i = offset; 0 <= i; i--) {
            if (this.isQuoteToriger(i, document)) {
                toriger = !toriger;
            }
            if (toriger) {
                continue;
            }
            char ch = document.getChar(i);
            if (ch == ';') {
                return true;
            }
            if ((ch == '\r') || (ch == '\n')) {
                break;
            }
        }
        return false;
    }

    private boolean doSharpSheck(int offset, IDocument document)
        throws BadLocationException {
        int next =
            EE2ELispBase.get().skipCharsForward(offset, " \t\r\n", document);
        next++;
        if (document.getLength() <= next + 1) {
            return false;
        }
        char char1 = document.getChar(next);
        char char2 = document.getChar(next + 1);
        if ((char1 == ';') && (char2 == ';')) {
            return true;
        }
        return false;
    }

    /**  getToriger   */
    protected boolean isNowTroiger(int offset, IDocument document)
        throws BadLocationException {
        boolean toriger = false;
        for (int i = 0; i < offset; i++) {
            if (this.isQuoteToriger(i, document)) {
                toriger = !toriger;
            }
            if (toriger) {
                continue;
            }
            char ch = document.getChar(i);
            if (ch == ';') {
                for (; i < offset; i++) {
                    ch = document.getChar(i);
                    if ((ch != '\r') && (ch != '\n')) {
                        continue;
                    }
                }
            }
        }
        return toriger;
    }
    /**  /[\\\\]*;/   */
    protected boolean isQuoteToriger(int offset, IDocument document)
        throws BadLocationException {
        if( (offset < 0) || (document.getLength() <= offset)) {
            return false;
        }
        char ch = document.getChar(offset);
        boolean ans = (ch == '\"');
        if( !ans ) {
            return false;
        }
        int count = 0;
        offset--;
        for( ; 0 <= offset ; offset--) {
            ch = document.getChar(offset);
            if( ch != '\\') {
                break;
            }
            count++;
        }
        return (count % 2) == 0;
    }
}
