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

package org.apache.jsieve;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.jsieve.exception.SieveException;
import org.apache.jsieve.mail.MailAdapter;
import org.apache.jsieve.parser.generated.ASTargument;
import org.apache.jsieve.parser.generated.ASTarguments;
import org.apache.jsieve.parser.generated.ASTblock;
import org.apache.jsieve.parser.generated.ASTcommand;
import org.apache.jsieve.parser.generated.ASTcommands;
import org.apache.jsieve.parser.generated.ASTstart;
import org.apache.jsieve.parser.generated.ASTstring;
import org.apache.jsieve.parser.generated.ASTstring_list;
import org.apache.jsieve.parser.generated.ASTtest;
import org.apache.jsieve.parser.generated.ASTtest_list;
import org.apache.jsieve.parser.generated.SieveParserVisitor;
import org.apache.jsieve.parser.generated.SimpleNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * Class SieveParserVisitorImpl defines the behaviour for each visited node in
 * the Sieve grammar. Each method corresponds to a node type and is invoked when
 * a node of that type is evaluated.
 * </p>
 * 
 * <p>
 * In essence, this class translates between the nodes operated on by the JavaCC
 * generated classes and the Sieve classes operated upon by the Commands, Tests
 * and Comparators. A visit to the start node, ASTstart, triggers evaluation of
 * all of its descendants.
 * </p>
 * 
 * <p>
 * See https://javacc.dev.java.net/doc/JJTree.html for indepth information about
 * Visitor support.
 * </p>
 * 
 * <p>
 * <strong>Note</strong> that this class is not thread safe. It's use should be
 * restricted to a single thread for the duration of a visit.
 * </p>
 */
public class SieveParserVisitorImpl implements SieveParserVisitor {
    private static final Logger LOGGER = LoggerFactory.getLogger(SieveParserVisitorImpl.class);

    private final SieveContext context;

    /**
     * Constructor for NodeVisitor.
     */
    public SieveParserVisitorImpl(final SieveContext context) {
        super();
        this.context = context;
    }

    /**
     * Method visitChildren adds the children of the node to the passed List.
     * 
     * @param node
     * @param data -
     *            Assumes a List
     * @return Object - A List
     * @throws SieveException
     */
    @SuppressWarnings("unchecked")
    protected Object visitChildren(SimpleNode node, Object data)
            throws SieveException {
        List children = new ArrayList(node.jjtGetNumChildren());
        node.childrenAccept(this, children);
        ((List) data).addAll(children);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTargument, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTargument node, Object data) throws SieveException {
        List<String> children = new ArrayList<String>(node.jjtGetNumChildren());
        Argument argument;

        if (null != node.getValue()) {
            argument = (Argument) node.getValue();
        } else {
            argument = new StringListArgument(((List) node.childrenAccept(this,
                    children)));
        }
        ((List) data).add(argument);

        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTarguments, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTarguments node, Object data) throws SieveException {
        List children = new ArrayList(node.jjtGetNumChildren());
        children = ((List) node.childrenAccept(this, children));

        // Extract Tests and TestList from the children
        Iterator childrenIter = children.iterator();
        TestList testList = null;
        List<Argument> argList = new ArrayList<Argument>(children.size());
        while (childrenIter.hasNext()) {
            Object next = childrenIter.next();
            if (next instanceof Test)
                testList = new TestList((Test) next);
            else if (next instanceof TestList)
                testList = (TestList) next;
            else if (next instanceof Argument) {
                argList.add((Argument)next);
            } else {
                LOGGER.error("Expected an 'Argument' but was {}", next);
            }
        }

        Arguments arguments = new Arguments(argList, testList);
        ((List) data).add(arguments);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTblock, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTblock node, Object data) throws SieveException {
        // if (node.jjtGetNumChildren() != 1)
        // throw new ParseException("Expecting exactly one 1 child");
        List children = new ArrayList(node.jjtGetNumChildren());
        Commands commands = (Commands) ((List) node.childrenAccept(this,
                children)).get(0);
        Block block = new Block(commands);
        ((List) data).add(block);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTcommand, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTcommand node, Object data) throws SieveException {
        List children = new ArrayList(node.jjtGetNumChildren());
        children = ((List) node.childrenAccept(this, children));

        // Extract the Arguments and Block from the children
        Iterator childrenIter = children.iterator();
        Arguments arguments = null;
        Block block = null;
        while (childrenIter.hasNext()) {
            Object next = childrenIter.next();
            if (next instanceof Arguments)
                arguments = (Arguments) next;
            else if (next instanceof Block)
                block = (Block) next;
        }

        context.setCoordinate(node.getCoordinate());
        final ScriptCoordinate coordinate = context.getCoordinate();
        Command command = new Command(node.getName(), arguments, block,
                coordinate);
        ((List) data).add(command);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTcommands, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTcommands node, Object data) throws SieveException {
        List<Command> children = new ArrayList<Command>(node.jjtGetNumChildren());
        Commands commands = new Commands(((List) node.childrenAccept(this,
                children)));
        ((List) data).add(commands);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTstart, Object)
     */
    public Object visit(ASTstart node, Object data) throws SieveException {
        // The data object must be the MailAdapter to process
        if (!(data instanceof MailAdapter))
            throw new SieveException("Expecting an instance of "
                    + MailAdapter.class.getName()
                    + " as data, received an instance of "
                    + (data == null ? "<null>" : data.getClass().getName())
                    + ".");

        // Start is an implicit Block
        // There will be one child, an instance of Commands
        List children = new ArrayList(node.jjtGetNumChildren());
        Commands commands = (Commands) ((List) node.childrenAccept(this,
                children)).get(0);
        Block block = new Block(commands);
        context.setCoordinate(node.getCoordinate());
        // Answer the result of executing the Block
        return block.execute((MailAdapter) data, context);
    }

    /**
     * @see SieveParserVisitor#visit(ASTstring_list, Object)
     */
    public Object visit(ASTstring_list node, Object data) throws SieveException {
        return visitChildren(node, data);
    }

    /**
     * @see SieveParserVisitor#visit(ASTstring, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTstring node, Object data) {
        // Strings are always surround by double-quotes
        final String value = (String) node.getValue();
        // A String is terminal, add it
        ((List) data).add(value);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTtest_list, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTtest_list node, Object data) throws SieveException {
        // return visitChildren(node, data);
        List<Test> children = new ArrayList<Test>(node.jjtGetNumChildren());
        TestList testList = new TestList(((List<Test>) node.childrenAccept(this,
                children)));
        ((List) data).add(testList);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(ASTtest, Object)
     */
    @SuppressWarnings("unchecked")
    public Object visit(ASTtest node, Object data) throws SieveException {
        List children = new ArrayList(node.jjtGetNumChildren());
        children = ((List) node.childrenAccept(this, children));

        // Extract the Arguments from the children
        Iterator childrenIter = children.iterator();
        Arguments arguments = null;
        while (childrenIter.hasNext()) {
            Object next = childrenIter.next();
            if (next instanceof Arguments)
                arguments = (Arguments) next;
        }

        context.setCoordinate(node.getCoordinate());
        Test test = new Test(node.getName(), arguments);
        ((List) data).add(test);
        return data;
    }

    /**
     * @see SieveParserVisitor#visit(SimpleNode, Object)
     */
    public Object visit(SimpleNode node, Object data) throws SieveException {
        return visitChildren(node, data);
    }

}
