/*
 * Created on 2003/06/14
 *
 * To change the template for this generated file go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 *
 * @author Toshikazu Ando [ ando@park.ruru.ne.jp ]
 */
package jp.sourceforge.projects.ee2e.core.cdt.doc;
import jp.sourceforge.projects.ee2e.core.EE2EDebug;

import java.io.Writer;
import java.io.BufferedReader;
import java.io.IOException;

/**
 * To change the template for this generated type comment go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
 *
 * @author Toshikazu Ando [ ando@park.ruru.ne.jp ]
 */
public class EE2ESharp implements EE2EDocument {

    public static final int NONE = 0;
    public static final int IF_DEF = 1;
    public static final int IF_NDEF = 2;
    public static final int ELSE = 3;
    public static final int ELSE_IF = 4;
    public static final int END_IF = 5;

    /** constractor */
    public EE2ESharp(String myString) {
        this.myString = myString;
        this.list = null;
        this.nextSharp = null;
    }

    /* (non-Javadoc)
     * @see jp.sourceforge.projects.ee2e.core.cdt.doc.EE2EDocument#createComposit(java.io.BufferedReader)
     */
    public boolean createComposit(BufferedReader reader) throws IOException {
        if (reader == null) {
            return false;
        }
        EE2EDebug.printf(10, "EE2ESharp::createComposit()");
        // data clear
        this.list = null;
        this.nextSharp = null;
        //
        while (true) {
            String line = reader.readLine();
            if (line == null) {
                break;
            }
            EE2EDocument document;
            int answer = this.checkSharp(line);
            if ((answer == IF_DEF) || (answer == IF_NDEF)) {
                document = new EE2ESharp(line);
                if (this.list == null) {
                    this.list = new java.util.LinkedList();
                }
                this.list.add(document);
            } else if ((answer == ELSE) || (answer == ELSE_IF)) {
                this.nextSharp = new EE2ESharp(line);
                return this.nextSharp.createComposit(reader);
            } else if (answer == END_IF) {
                return true; // not null
            } else { // NONE
                document = new EE2EString(line);
                if (this.list == null) {
                    this.list = new java.util.LinkedList();
                }
                this.list.add(document);
            }
            if (!document.createComposit(reader)) {
                break;
            }
        }
        return false;
    }
    /* (non-Javadoc)
     * @see jp.sourceforge.projects.ee2e.core.cdt.doc.EE2EDocument#destoryTarget(java.lang.String, boolean, boolean)
     */
    public void destoryTarget(String target, boolean ifOrElse) {
        if (target == null) {
            return;
        }
        if (this.list != null) {
            java.util.Iterator ite = this.list.iterator();
            while (ite.hasNext()) {
                EE2EDocument document = (EE2EDocument) ite.next();
                document.destoryTarget(target, ifOrElse);
            }
        }
        if (this.nextSharp != null) {
            this.nextSharp.destoryTarget(target, ifOrElse);
        }
        String myTargetString = this.devideSharp(this.myString);
        if ((myTargetString != null) && myTargetString.equals(target)) {
            EE2EDebug.printf(10, "EE2ESharp::destoryTarget() hit!");
            int state = this.checkSharp(this.myString); // before clear
            this.myString = ""; //change status
            if (((ifOrElse) && ((state == IF_DEF) || (state == ELSE_IF)))
                || ((!ifOrElse) && ((state == IF_NDEF) || (state == ELSE)))) {
                this.list = null;
            } else {
                this.nextSharp = null;
            }
        }
    }
    /* (non-Javadoc)
     * @see jp.sourceforge.projects.ee2e.core.cdt.doc.EE2EDocument#getWriter(java.io.Writer)
     */
    public void getWriter(Writer writer, boolean flag) throws IOException {
        if (writer == null) {
            return;
        }
        int answer = this.checkSharp(this.myString);
        boolean firstFlag = false;
        if ((answer == IF_DEF) || (answer == IF_NDEF)) {
            firstFlag = true;
            writer.write(this.myString);
            writer.write("\n");
        } else if (answer == ELSE) {
            if (flag == true) {
                writer.write(this.myString);
                writer.write("\n");
            }
        } else if (answer == ELSE_IF) {
            if (flag == true) {
                writer.write(this.myString);
                writer.write("\n");
            } else {
                writer.write("#if ");
                writer.write(this.devideSharp(this.myString));
                writer.write("\n");
                firstFlag = true;
            }
        } else {
            /*EMPTY*/
        }
        if (this.list != null) {
            java.util.Iterator ite = this.list.iterator();
            while (ite.hasNext()) {
                EE2EDocument doc = (EE2EDocument) ite.next();
                doc.getWriter(writer, false);
            }
        }
        if (this.nextSharp != null) {
            this.nextSharp.getWriter(writer, firstFlag | flag);
        }
        if (firstFlag) {
            writer.write("#endif\n");
        }
    }
    /* (non-Javadoc)
     * @see jp.sourceforge.projects.ee2e.core.cdt.doc.EE2EDocument#getDefines()
     */
    public void getDefines(java.util.Collection collection) {
        String res = this.devideSharp(this.myString);
        if ((res != null) && (!res.equals(""))) {
            collection.add(res);
        }
        if (this.list != null) {
            java.util.Iterator ite = this.list.iterator();
            while (ite.hasNext()) {
                EE2EDocument doc = (EE2EDocument) ite.next();
                doc.getDefines(collection);
            }
        }
        if (this.nextSharp != null) {
            this.nextSharp.getDefines(collection);
        }
    }
    /** "#if AAA" -> "AAA"
    * "#error other sharp" -> ""
    * "    notsharp();" -> ""
    * @param line input string
    * @return output string
    */
    protected String devideSharp(String line) {
        int answer = this.checkSharp(line);
        if ((answer == NONE) || (answer == END_IF)) {
            return null;
        }
        //
        line = this.deleteSpace(line);
        if (line == null) {
            return null;
        }
        while (0 < line.length()) { // "#if AAA" -> " AA"
            if (line.charAt(0) == ' ') {
                break;
            }
            line = line.substring(1);
        }
        if ((0 < line.length()) && (line.charAt(0) == ' ')) { // " AA" -> "A"
            line = line.substring(1);
        }
        return line;
    }

    /** get sharp comment */
    protected int checkSharp(String line) {
        line = this.deleteSpace(line);
        if (line == null) {
            return NONE;
        }
        if (line.indexOf("#ifndef") == 0) {
            return IF_NDEF;
        }
        if (line.indexOf("#ifdef") == 0) {
            return IF_DEF;
        }
        if (line.indexOf("#elseif") == 0) {
            return ELSE_IF;
        }
        if (line.indexOf("#elsif") == 0) {
            return ELSE_IF;
        }
        if (line.indexOf("#elif") == 0) {
            return ELSE_IF;
        }
        if (line.indexOf("#else") == 0) {
            return ELSE;
        }
        if (line.indexOf("#endif") == 0) {
            return END_IF;
        }
        if (line.indexOf("#end") == 0) {
            return END_IF;
        }
        if (line.indexOf("#if") == 0) {
            return IF_DEF;
        }
        return NONE;
    }

    /** "  #if\t\tAAA" -> "#if AAA"
    * "    notsharp();" -> ""
    * @param line input string
    * @return output string,
    * "hogehoge(); #if AAA"
    */
    protected String deleteSpace(String line) {
        if (line == null) {
            return null;
        }
        line = EE2ESharp.deleteSpaceAndComment(line);

        while (true) { // "#if\tAA" -> "#if AA"
            int index = line.indexOf("\t");
            if (index < 0) {
                break;
            }
            line = line.substring(0, index) + " " + line.substring(index + 1);
        }
        while (true) { // "#if\tAA" -> "#if AA"
            int index = line.indexOf("\r");
            if (index < 0) {
                break;
            }
            line = line.substring(0, index) + " " + line.substring(index + 1);
        }
        while (true) { // "#if\tAA" -> "#if AA"
            int index = line.indexOf("\n");
            if (index < 0) {
                break;
            }
            line = line.substring(0, index) + " " + line.substring(index + 1);
        }
        while (3 < line.length()) { // "#if   AA" -> "#if AA"
            int index = line.indexOf("  ");
            if (index < 0) {
                break;
            }
            line = line.substring(0, index + 1) + line.substring(index + 2);
        }
        if ((3 < line.length())
            && (line.charAt(0) == ' ')) { // " #if" -> "#if"
            line = line.substring(1);
        }
        int index = line.indexOf("# ");
        if (0 < index) { // "# if" -> "#if"
            line = line.substring(0, index) + line.substring(index + 2);
        }
        if ((line.length() <= 0) || (line.charAt(0) != '#')) {
            return null;
        }
        return line;
    }
    /** getter function */
    protected String getMyString() {
        return this.myString;
    }
    /** getter function */
    protected java.util.List getList() {
        return this.list;
    }
    /** getter function */
    protected EE2ESharp getSharp() {
        return this.nextSharp;
    }
    public static String deleteSpaceAndComment(String line) {
        if ((line == null) || line.equals("")) {
            return "";
        }
        int index = line.indexOf("//");
        if (0 <= index) {
            line = line.substring(0, index);
        }
        while (true) { // "#if\tAA" -> "#if AA"
            int leftIndex = line.indexOf("/*");
            int rightIndex = line.indexOf("*/");
            if ((leftIndex < 0) || (rightIndex <= leftIndex)) {
                break;
            }
            line =
                line.substring(0, leftIndex) + line.substring(rightIndex + 2);
        }
        while (true) { // "#if AA  " -> "#if AA"
            if ((0 < line.length())
                && ((line.charAt(line.length() - 1) == ' ')
                    || (line.charAt(line.length() - 1) == '\r')
                    || (line.charAt(line.length() - 1) == '\t')
                    || (line.charAt(line.length() - 1) == '\n'))) {
                line = line.substring(0, line.length() - 1);
            } else {
                break;
            }
        }
        return line;
    }
    private String myString;
    private java.util.List list;
    private EE2ESharp nextSharp;
}
