/*
 * 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.axis2.engine;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.HandlerDescription;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.description.PhaseRule;
import org.apache.axis2.phaseresolver.PhaseException;
import org.apache.axis2.util.LoggingControl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * A Phase is an ordered collection of Handlers.
 */
public class Phase implements Handler {

    public static final String ALL_PHASES = "*";

    /**
     * Field log
     */
    private static final Log log = LogFactory.getLog(Phase.class);
    private static boolean isDebugEnabled = LoggingControl.debugLoggingAllowed && log.isDebugEnabled();

    /**
     * Field handlers
     */
    private List<Handler> handlers;

    /**
     * A handler has been marked as present in both the first phase and the last phase
     */
    private boolean isOneHandler;

    /**
     * Field phaseName
     */
    private String phaseName;

    /**
     * Field phaseFirstSet
     */
    private boolean phaseFirstSet;

    /**
     * Field phaseLastSet
     */
    private boolean phaseLastSet;

    /**
     * Default constructor
     */
    public Phase() {
        this(null);
    }

    /**
     * Create a named Phase
     *
     * @param phaseName the name for this Phase
     */
    public Phase(String phaseName) {
        handlers = new CopyOnWriteArrayList<Handler>();
        this.phaseName = phaseName;
    }

    /**
     * Add a handler to the Phase.
     *
     * @param handler the Handler to add
     */
    public void addHandler(Handler handler) {
        log.debug("Handler " + handler.getName() + " added to Phase " + phaseName);

        if (phaseLastSet) {
            // handlers.size() can not be 0 , since when setting phase last it is always > 0
            if (handlers.size() == 1) {
                handlers.add(0, handler);
            } else {
                handlers.add(handlers.size() - 2, handler);
            }
        } else {
            handlers.add(handler);
        }
    }

    /**
     * Add a HandlerDescription to the Phase
     *
     * @param handlerDesc the HandlerDescription to add
     * @throws PhaseException if there is a problem
     */
    public void addHandler(HandlerDescription handlerDesc) throws PhaseException {
        Iterator<Handler> handlers_itr = getHandlers().iterator();

        while (handlers_itr.hasNext()) {
            Handler hand = (Handler) handlers_itr.next();
            HandlerDescription thisDesc = hand.getHandlerDesc();
            if (handlerDesc.getName().equals(thisDesc.getName())) {
                return;
            }
        }

        if (isOneHandler) {
            throw new PhaseException("Phase '" + this.getPhaseName()
                    + "' can only have one handler, since there is a "
                    + "handler with both phaseFirst and phaseLast true ");
        }

        if (handlerDesc.getRules().isPhaseFirst() && handlerDesc.getRules().isPhaseLast()) {
            if (!handlers.isEmpty()) {
                throw new PhaseException(this.getPhaseName()
                        + " already contains Handlers, and "
                        + handlerDesc.getName()
                        + " cannot therefore be both phaseFirst and phaseLast.");
            } else {
                handlers.add(handlerDesc.getHandler());
                isOneHandler = true;
            }
        } else if (handlerDesc.getRules().isPhaseFirst()) {
            setPhaseFirst(handlerDesc.getHandler());
        } else if (handlerDesc.getRules().isPhaseLast()) {
            setPhaseLast(handlerDesc.getHandler());
        } else {
            insertHandler(handlerDesc);
        }
    }

    /**
     * Add a Handler at a particular index within the Phase.
     *
     * If we have a Phase with (H1, H2), calling addHandler(H3, 1) will result in (H1, H3, H2)
     *
     * @param handler the Handler to add
     * @param index the position in the Phase at which to place the Handler
     */
    public void addHandler(Handler handler, int index) {
        if (log.isDebugEnabled()) {
            log.debug("Handler " + handler.getName() + " inserted at position " + index +
                    " of Phase " + phaseName);
        }
        handlers.add(index, handler);
    }

    /**
     * Confirm that all post-conditions of this Phase are met.  After all Handlers in a
     * Phase are invoke()d, this method will be called.  Subclasses should override it in order
     * to confirm that the purpose of the given Phase has been acheived.
     *
     * @param msgContext the active MessageContext
     * @throws AxisFault if a post-condition has not been met, or other problems occur
     */
    public void checkPostConditions(MessageContext msgContext) throws AxisFault {
        // Default version does nothing
    }

    /**
     * Check the preconditions for a Phase.  This method will be called when the Phase is
     * invoked, BEFORE any Handlers are invoked.  Subclasses should override it in order
     * to confirm that necessary preconditions are met before the Phase does its work.  They
     * should throw an appropriate AxisFault if not.
     *
     * @param msgContext the active MessageContext
     * @throws AxisFault if a precondition is not met, or in case of other problem
     */
    public void checkPreconditions(MessageContext msgContext) throws AxisFault {
        // Default version does nothing
    }

    public void cleanup() {
        // Default version does nothing
    }

    public void init(HandlerDescription handlerdesc) {
        // Default version does nothing
    }

    private void insertHandler(HandlerDescription handlerDesc) throws PhaseException {
        Handler handler = handlerDesc.getHandler();
        PhaseRule rules = handler.getHandlerDesc().getRules();
        String beforeName = rules.getBefore();
        String afterName = rules.getAfter();

        // If we don't care where it goes, tack it on at the end
        if (beforeName == null && afterName == null) {
            addHandler(handler);
            return;
        }

        // Otherwise walk the list and find the right place to put it
        int beforeIndex = -1, afterIndex = -1;

        for (int i = 0; i < handlers.size(); i++) {
            Handler tempHandler = (Handler) handlers.get(i);

            if ((beforeName != null) && (beforeIndex == -1)) {
                if (tempHandler.getName().equals(beforeName)) {
                    // Found the "before" handler
                    beforeIndex = i;
                }
            }

            if ((afterName != null) && (afterIndex == -1)) {
                if (tempHandler.getName().equals(afterName)) {
                    // Found the "after" handler
                    afterIndex = i;
                }
            }
        }

        if ((beforeIndex > -1) && (afterIndex >= beforeIndex)) {
            throw new PhaseException("Can't insert handler because " + beforeName + " is before " +
                    afterName + " in Phase '" + phaseName + "'");
        }

        if (phaseFirstSet && beforeIndex == 0) {
            throw new PhaseException("Can't insert handler before handler '"
                    + beforeName
                    + "', which is marked phaseFirst");
        }

        if (phaseLastSet && afterIndex == (handlers.size() - 1)) {
            throw new PhaseException("Can't insert handler after handler '"
                    + afterName
                    + "', which is marked phaseLast");
        }

        if (beforeIndex > -1) {
            handlers.add(beforeIndex, handler);
        } else if (afterIndex > -1){
            if (phaseLastSet){
                if (handlers.size() ==1){
                    handlers.add(0,handler);
                }  else {
                    handlers.add(handlers.size() -2,handler);
                }
            }  else {
                if (afterIndex == (handlers.size() -1)) {
                    handlers.add(handler);
                } else {
                    handlers.add(afterIndex +1,handler);
                }
            }
        }  else {
            if (phaseLastSet) {
                if (handlers.size() ==1){
                    handlers.add(0,handler);
                }  else {
                    handlers.add(handlers.size() -2,handler);
                }
            }    else {
                handlers.add(handler);
            }
        }
    }

    /**
     * Invoke all the handlers in this Phase
     *
     * @param msgctx the current MessageContext
     * @return An InvocationResponse that indicates what
     *         the next step in the message processing should be.
     * @throws org.apache.axis2.AxisFault
     */
    public final InvocationResponse invoke(MessageContext msgctx) throws AxisFault {
        
        if (isDebugEnabled) {
            log.debug(msgctx.getLogIDString() + " Checking pre-condition for Phase \"" + phaseName +
                    "\"");
        }

        InvocationResponse pi = InvocationResponse.CONTINUE;

        int currentIndex = msgctx.getCurrentPhaseIndex();

        if (currentIndex == 0) {
            checkPreconditions(msgctx);
        }

        if (isDebugEnabled) {
            log.debug(msgctx.getLogIDString() + " Invoking phase \"" + phaseName + "\"");
        }

        int handlersSize = handlers.size();
        
        while (currentIndex < handlersSize) {
            Handler handler = (Handler) handlers.get(currentIndex);

            if (isDebugEnabled) {
                log.debug(msgctx.getLogIDString() + " Invoking Handler '" + handler.getName() +
                        "' in Phase '" + phaseName + "'");
            }
            pi = handler.invoke(msgctx);

            if (!pi.equals(InvocationResponse.CONTINUE)) {
                return pi;
            }

            currentIndex++;
            msgctx.setCurrentPhaseIndex(currentIndex);
        }

        if (isDebugEnabled) {
            log.debug(msgctx.getLogIDString() + " Checking post-conditions for phase \"" +
                    phaseName + "\"");
        }

        msgctx.setCurrentPhaseIndex(0);
        checkPostConditions(msgctx);
        return pi;
    }

    public void flowComplete(MessageContext msgContext) {
        if (isDebugEnabled) {
            log.debug(msgContext.getLogIDString() + " Invoking flowComplete() in Phase \"" +
                    phaseName + "\"");
        }

        // This will be non-zero if we failed during execution of one of the
        // handlers in this phase
        int currentHandlerIndex = msgContext.getCurrentPhaseIndex();
        if (currentHandlerIndex == 0) {
            currentHandlerIndex = handlers.size();
        } else {
            /*We need to set it to 0 so that any previous phases will execute all
         * of their handlers.*/
            msgContext.setCurrentPhaseIndex(0);
        }

        for (; currentHandlerIndex > 0; currentHandlerIndex--) {
            Handler handler = (Handler) handlers.get(currentHandlerIndex - 1);

            if (isDebugEnabled) {
                log.debug(msgContext.getLogIDString() + " Invoking flowComplete() for Handler '" +
                        handler.getName() + "' in Phase '" + phaseName + "'");
            }

            handler.flowComplete(msgContext);
        }
    }

    public String toString() {
        return this.getPhaseName();
    }

    public int getHandlerCount() {
        return handlers.size();
    }

    public HandlerDescription getHandlerDesc() {
        return null;
    }

    /**
     * Gets all the handlers in the phase.
     *
     * @return Returns an ArrayList of Handlers
     */
    public List<Handler> getHandlers() {
        return handlers;
    }

    public String getName() {
        return phaseName;
    }

    public Parameter getParameter(String name) {
        return null;
    }

    /**
     * @return Returns the name.
     */
    public String getPhaseName() {
        return phaseName;
    }

    public void setName(String phaseName) {
        this.phaseName = phaseName;
    }

    /**
     * Add a Handler to the Phase in the very first position, and ensure no other Handler
     * will come before it.
     *
     * @param handler the Handler to add
     * @throws PhaseException if another Handler is already set as phaseFirst
     */
    public void setPhaseFirst(Handler handler) throws PhaseException {
        if (phaseFirstSet) {
            throw new PhaseException("PhaseFirst has been set already, cannot have two"
                    + " phaseFirst Handlers for Phase '" + this.getPhaseName() + "'");
        }
        handlers.add(0, handler);
        phaseFirstSet = true;
    }

    /**
     * Add a Handler to the Phase in the very last position, and ensure no other Handler
     * will come after it.
     *
     * @param handler the Handler to add
     * @throws PhaseException if another Handler is already set as phaseLast
     */
    public void setPhaseLast(Handler handler) throws PhaseException {
        if (phaseLastSet) {
            throw new PhaseException("PhaseLast already has been set,"
                    + " cannot have two PhaseLast Handler for same phase "
                    + this.getPhaseName());
        }

        handlers.add(handler);
        phaseLastSet = true;
    }

    /**
     * Remove a given Handler from a phase using a HandlerDescription
     *
     * @param handlerDesc the HandlerDescription to remove
     */
    public void removeHandler(HandlerDescription handlerDesc) {
        if (handlers.remove(handlerDesc.getHandler())) {
            PhaseRule rule = handlerDesc.getRules();
            if (rule.isPhaseFirst()) {
                phaseFirstSet = false;
            }
            if (rule.isPhaseLast()) {
                phaseLastSet = false;
            }
            if (rule.isPhaseFirst() && rule.isPhaseLast()) {
                isOneHandler = false;
            }
            log.debug("removed handler " + handlerDesc.getName()
                    + " from the phase " + phaseName);
        } else {
            log.debug("unable to remove handler " + handlerDesc.getName()
                    + " from the phase " + phaseName);
        }
    }

}
