/* Copyright (C) 2004-2007  The Chemistry Development Kit (CDK) project
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * (or see http://www.gnu.org/copyleft/lesser.html)
 */
package org.openscience.cdk.smiles.smarts.parser;

/**
 * An AST tree visitor. It is a prototype that translate Smarts to MQL.
 * It is far from fully functioning.
 *
 * @author Dazhi Jiao
 * @cdk.created 2007-04-24
 * @cdk.module smarts
 * @cdk.githash
 * @cdk.keyword SMARTS AST
 */
@Deprecated
public class Smarts2MQLVisitor implements SMARTSParserVisitor {

    public Object visit(ASTRingIdentifier node, Object data) {
        // TODO Auto-generated method stub
        return null;
    }

    String  symbolIdentified = "";
    boolean not              = false;

    public Object visit(ASTAtom node, Object data) {
        // TODO Auto-generated method stub
        return null;
    }

    public Object visit(SimpleNode node, Object data) {
        return node.childrenAccept(this, data);
    }

    public Object visit(ASTStart node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    public Object visit(ASTReaction node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    public Object visit(ASTGroup node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    public Object visit(ASTSmarts node, Object data) {
        String local = "";
        for (int i = 0; i < node.jjtGetNumChildren(); i++) {
            Node child = node.jjtGetChild(i);
            if (child instanceof ASTAtom) {
                local = (String) child.jjtAccept(this, local);
            } else if (child instanceof ASTLowAndBond) {
                i++;
                Node nextChild = node.jjtGetChild(i); // the next child should
                // be another smarts
                String bond = (String) child.jjtAccept(this, local);
                local = local + bond;
                local = (String) nextChild.jjtAccept(this, local);
            } else if (child instanceof ASTSmarts) { // implicit single bond
                if (!"".equals(local)) local = local + "-";
                local = (String) child.jjtAccept(this, local);
            } else if (child instanceof ASTExplicitAtom) {
                if (!"".equals(local)) local = local + "-";
                local = (String) child.jjtAccept(this, local);
            }
        }
        return data + local;
    }

    // TODO: Accept only one bond. Need to find out whether MQL supports
    // logical bonds
    public Object visit(ASTLowAndBond node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    // TODO: Accept only one bond. Need to find out whether MQL supports
    // logical bonds
    public Object visit(ASTOrBond node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    // TODO: Accept only one bond. Need to find out whether MQL supports
    // logical bonds
    public Object visit(ASTExplicitHighAndBond node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    // TODO: Accept only one bond. Need to find out whether MQL supports
    // logical bonds
    public Object visit(ASTImplicitHighAndBond node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    // TODO: Accept only one bond. Need to find out whether MQL supports
    // logical bonds
    public Object visit(ASTNotBond node, Object data) {
        return node.jjtGetChild(0).jjtAccept(this, data);
    }

    public Object visit(ASTSimpleBond node, Object data) {
        String bond = "";
        int bondType = node.getBondType();
        switch (bondType) {
            case SMARTSParserConstants.ANY_BOND:
                bond = "~";
                break;
            case SMARTSParserConstants.S_BOND:
                bond = "-";
                break;
            case SMARTSParserConstants.D_BOND:
                bond = "=";
                break;
            case SMARTSParserConstants.T_BOND:
                bond = "#";
                break;
            case SMARTSParserConstants.AR_BOND:
                bond = ":";
                break;
            case SMARTSParserConstants.R_BOND:
                bond = "$~1"; // TODO: only one ring is assumed here. Should handle more
                break;
            case SMARTSParserConstants.UP_S_BOND:
            case SMARTSParserConstants.DN_S_BOND:
            case SMARTSParserConstants.UP_OR_UNSPECIFIED_S_BOND:
            case SMARTSParserConstants.DN_OR_UNSPECIFIED_S_BOND:
                bond = "-";
                break;
        }
        return bond;
    }

    public Object visit(ASTExplicitAtom node, Object data) {
        data = data + node.getSymbol(); // TODO: ring handling!
        return data;
    }

    public Object visit(ASTLowAndExpression node, Object data) {
        String left = (String) node.jjtGetChild(0).jjtAccept(this, data);
        if (node.jjtGetNumChildren() == 1) {
            return left;
        }
        String right = (String) node.jjtGetChild(1).jjtAccept(this, data);
        if ("".equals(left)) {
            return right;
        } else if ("".equals(right)) {
            return left;
        } else {
            return left + "&" + right;
        }
    }

    public Object visit(ASTOrExpression node, Object data) {
        String left = (String) node.jjtGetChild(0).jjtAccept(this, data);
        if (node.jjtGetNumChildren() == 1) {
            return left;
        }
        String right = (String) node.jjtGetChild(1).jjtAccept(this, data);
        if ("".equals(left)) {
            return right;
        } else if ("".equals(right)) {
            return left;
        } else {
            return left + "|" + right;
        }
    }

    // TODO: the precedence needs to be addressed
    public Object visit(ASTExplicitHighAndExpression node, Object data) {
        String left = (String) node.jjtGetChild(0).jjtAccept(this, data);
        if (node.jjtGetNumChildren() == 1) {
            return left;
        }
        String right = (String) node.jjtGetChild(1).jjtAccept(this, data);
        if ("".equals(left)) {
            return right;
        } else if ("".equals(right)) {
            return left;
        } else {
            return left + "&" + right;
        }
    }

    //  TODO: the precedence needs to be addressed
    public Object visit(ASTImplicitHighAndExpression node, Object data) {
        String left = (String) node.jjtGetChild(0).jjtAccept(this, data);
        if (node.jjtGetNumChildren() == 1) {
            return left;
        }
        String right = (String) node.jjtGetChild(1).jjtAccept(this, data);
        if ("".equals(left)) {
            return right;
        } else if ("".equals(right)) {
            return left;
        } else {
            return left + "&" + right;
        }
    }

    public Object visit(ASTNotExpression node, Object data) {
        // well, I know there is a not in MQL :)
        if (node.getType() == SMARTSParserConstants.NOT) {
            not = true;
        } else {
            not = false;
        }
        String str = "";
        for (int i = 0; i < node.jjtGetNumChildren(); i++) {
            str += node.jjtGetChild(i).jjtAccept(this, data);
        }
        return str;
    }

    // TODO: I don't think this is implemented in MQL. Throw an exception/warning?
    public Object visit(ASTRecursiveSmartsExpression node, Object data) {
        return null;
    }

    public Object visit(ASTTotalHCount node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTImplicitHCount node, Object data) {
        // TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTExplicitConnectivity node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTAtomicNumber node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTHybrdizationNumber node, Object data) {
        return data;
    }

    public Object visit(ASTCharge node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTRingConnectivity node, Object data) {

        return data;
    }

    public Object visit(ASTPeriodicGroupNumber node, Object data) {
        return data;
    }

    public Object visit(ASTTotalConnectivity node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTValence node, Object data) {
        //      TODO: a property? not sure. just making things up here :)
        return data;
    }

    public Object visit(ASTRingMembership node, Object data) {
        //      TODO: "ring" is a property, but how about the number of rings?
        return "ring";
    }

    public Object visit(ASTSmallestRingSize node, Object data) {
        return data;
    }

    public Object visit(ASTAliphatic node, Object data) {
        return data;
    }

    public Object visit(ASTNonCHHeavyAtom node, Object data) {
        return data;
    }

    public Object visit(ASTAromatic node, Object data) {
        return data;
    }

    public Object visit(ASTAnyAtom node, Object data) {
        return data;
    }

    public Object visit(ASTAtomicMass node, Object data) {
        return data;
    }

    public Object visit(ASTChirality node, Object data) {
        return data;
    }

    public Object visit(ASTElement node, Object data) {
        symbolIdentified = node.getSymbol();
        return "";
    }

}
