/**
 * 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.cxf.phase;

import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.common.util.PropertyUtils;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.continuations.SuspendedInvocationException;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.InterceptorChain;
import org.apache.cxf.interceptor.ServiceInvokerInterceptor;
import org.apache.cxf.logging.FaultListener;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.FaultMode;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.OperationInfo;
import org.apache.cxf.transport.MessageObserver;

/**
 * A PhaseInterceptorChain orders Interceptors according to the phase they
 * participate in and also according to the before & after properties on an
 * Interceptor.
 * <p>
 * A List of phases is supplied to the PhaseInterceptorChain in the constructor.
 * This class is typically instantiated from the PhaseChainCache class in this
 * package. Interceptors that are added to the chain are ordered by phase.
 * Within a phase, interceptors can order themselves. Each PhaseInterceptor
 * has an ID. PhaseInterceptors can supply a Collection of IDs which they
 * should run before or after, supplying fine grained ordering.
 * <p>
 *
 */
public class PhaseInterceptorChain implements InterceptorChain {
    public static final String PREVIOUS_MESSAGE = PhaseInterceptorChain.class.getName() + ".PREVIOUS_MESSAGE";

    private static final Logger LOG = LogUtils.getL7dLogger(PhaseInterceptorChain.class);

    private static final ThreadLocal<Message> CURRENT_MESSAGE = new ThreadLocal<>();

    private final Map<String, Integer> nameMap;
    private final Phase[] phases;

    // heads[phase] refers to the first interceptor of the given phase
    private InterceptorHolder[] heads;
    // tails[phase] refers to the last interceptor of the given phase
    private InterceptorHolder[] tails;
    // hasAfters[phase] indicates that the given phase has already inserted
    // interceptors that may need to be placed after future to-be-inserted
    // interceptors.  This flag is used to activate ordering of interceptors
    // when new ones are added to the list for this phase.
    // Note no hasBefores[] is needed because implementation adds subsequent
    // interceptors to the end of the list by default.
    private boolean[] hasAfters;


    private State state;
    private Message pausedMessage;
    private MessageObserver faultObserver;
    private PhaseInterceptorIterator iterator;
    private final boolean isFineLogging;

    // currently one chain for one request/response, use below as signal
    // to avoid duplicate fault processing on nested calling of
    // doIntercept(), which will throw same fault multi-times
    private boolean faultOccurred;
    private boolean chainReleased;


    private PhaseInterceptorChain(PhaseInterceptorChain src) {
        isFineLogging = LOG.isLoggable(Level.FINE);

        //only used for clone
        state = State.EXECUTING;

        //immutable, just repoint
        nameMap = src.nameMap;
        phases = src.phases;

        int length = phases.length;
        hasAfters = new boolean[length];
        System.arraycopy(src.hasAfters, 0, hasAfters, 0, length);

        heads = new InterceptorHolder[length];
        tails = new InterceptorHolder[length];

        InterceptorHolder last = null;
        for (int x = 0; x < length; x++) {
            InterceptorHolder ih = src.heads[x];
            while (ih != null
                && ih.phaseIdx == x) {
                InterceptorHolder ih2 = new InterceptorHolder(ih);
                ih2.prev = last;
                if (last != null) {
                    last.next = ih2;
                }
                if (heads[x] == null) {
                    heads[x] = ih2;
                }
                tails[x] = ih2;
                last = ih2;
                ih = ih.next;
            }
        }
    }

    public PhaseInterceptorChain(SortedSet<Phase> ps) {
        state = State.EXECUTING;
        isFineLogging = LOG.isLoggable(Level.FINE);

        int numPhases = ps.size();
        phases = new Phase[numPhases];
        nameMap = new HashMap<>();

        heads = new InterceptorHolder[numPhases];
        tails = new InterceptorHolder[numPhases];
        hasAfters = new boolean[numPhases];

        int idx = 0;
        for (Phase phase : ps) {
            phases[idx] = phase;
            nameMap.put(phase.getName(), idx);
            ++idx;
        }
    }

    public static Message getCurrentMessage() {
        return CURRENT_MESSAGE.get();
    }

    public static boolean setCurrentMessage(PhaseInterceptorChain chain, Message m) {
        if (getCurrentMessage() == m) {
            return false;
        }
        if (chain.iterator.hasPrevious()) {
            chain.iterator.previous();
            if (chain.iterator.next() instanceof ServiceInvokerInterceptor) {
                CURRENT_MESSAGE.set(m);
                return true;
            }
            String error = "Only ServiceInvokerInterceptor can update the current chain message";
            LOG.warning(error);
            throw new IllegalStateException(error);
        }
        return false;

    }

    public synchronized State getState() {
        return state;
    }

    public synchronized void releaseAndAcquireChain() {
        while (!chainReleased) {
            try {
                this.wait();
            } catch (InterruptedException ex) {
                // ignore
            }
        }
        chainReleased = false;
    }

    public synchronized void releaseChain() {
        this.chainReleased = true;
        this.notifyAll();
    }

    public PhaseInterceptorChain cloneChain() {
        return new PhaseInterceptorChain(this);
    }

    private void updateIterator() {
        if (iterator == null) {
            iterator = new PhaseInterceptorIterator(heads);
            outputChainToLog(false);
        }
    }

    public void add(Collection<Interceptor<? extends Message>> newhandlers) {
        add(newhandlers, false);
    }

    public void add(Collection<Interceptor<? extends Message>> newhandlers, boolean force) {
        if (newhandlers == null) {
            return;
        }

        for (Interceptor<? extends Message> handler : newhandlers) {
            add(handler, force);
        }
    }

    public void add(Interceptor<? extends Message> i) {
        add(i, false);
    }

    public void add(Interceptor<? extends Message> i, boolean force) {
        PhaseInterceptor<? extends Message> pi = (PhaseInterceptor<? extends Message>)i;

        String phaseName = pi.getPhase();
        Integer phase = nameMap.get(phaseName);

        if (phase == null) {
            LOG.warning("Skipping interceptor " + i.getClass().getName()
                + ((phaseName == null) ? ": Phase declaration is missing."
                : ": Phase " + phaseName + " specified does not exist."));
        } else {
            if (isFineLogging) {
                LOG.fine("Adding interceptor " + i + " to phase " + phaseName);
            }

            insertInterceptor(phase, pi, force);
        }
        Collection<PhaseInterceptor<? extends Message>> extras
            = pi.getAdditionalInterceptors();
        if (extras != null) {
            for (PhaseInterceptor<? extends Message> p : extras) {
                add(p, force);
            }
        }
    }

    public synchronized void pause() {
        state = State.PAUSED;
        pausedMessage = CURRENT_MESSAGE.get();
    }
    public synchronized void unpause() {
        if (state == State.PAUSED || state == State.SUSPENDED) {
            state = State.EXECUTING;
            pausedMessage = null;
        }
    }

    public synchronized void suspend() {
        state = State.SUSPENDED;
        pausedMessage = CURRENT_MESSAGE.get();
    }

    public synchronized void resume() {
        if (state == State.PAUSED || state == State.SUSPENDED) {
            state = State.EXECUTING;
            Message m = pausedMessage;
            pausedMessage = null;
            doIntercept(m);
        }
    }

    /**
     * Intercept a message, invoking each phase's handlers in turn.
     *
     * @param message the message
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public synchronized boolean doIntercept(Message message) {
        updateIterator();

        Message oldMessage = CURRENT_MESSAGE.get();
        try {
            CURRENT_MESSAGE.set(message);
            if (oldMessage != null
                && !message.containsKey(PREVIOUS_MESSAGE)
                && message != oldMessage
                && message.getExchange() != oldMessage.getExchange()) {
                message.put(PREVIOUS_MESSAGE, new WeakReference<Message>(oldMessage));
            }
            while (state == State.EXECUTING && iterator.hasNext()) {
                try {
                    Interceptor<Message> currentInterceptor = (Interceptor<Message>)iterator.next();
                    if (isFineLogging) {
                        LOG.fine("Invoking handleMessage on interceptor " + currentInterceptor);
                    }
                    //System.out.println("-----------" + currentInterceptor);
                    currentInterceptor.handleMessage(message);
                    if (state == State.SUSPENDED) {
                         // throw the exception to make sure thread exit without interrupt
                        throw new SuspendedInvocationException();
                    }

                } catch (SuspendedInvocationException ex) {

                    // Moving the chain iterator to the previous interceptor is needed
                    // for the invocation to be resumed from the same interceptor which
                    // suspended the invocation.
                    // If "suspend.chain.on.current.interceptor" is set to true then
                    // the chain will be resumed from the interceptor which follows
                    // the interceptor which suspended the invocation.
                    Object suspendProp = message.remove("suspend.chain.on.current.interceptor");
                    if ((suspendProp == null || PropertyUtils.isFalse(suspendProp))
                        && iterator.hasPrevious()) {
                        iterator.previous();
                    }
                    pause();
                    throw ex;
                } catch (RuntimeException ex) {
                    if (!faultOccurred) {
                        faultOccurred = true;
                        wrapExceptionAsFault(message, ex);
                    }
                    state = State.ABORTED;
                }
            }
            if (state == State.EXECUTING) {
                state = State.COMPLETE;
            }
            return state == State.COMPLETE;
        } finally {
            CURRENT_MESSAGE.set(oldMessage);
        }
    }

    private void wrapExceptionAsFault(Message message, RuntimeException ex) {
        String description = getServiceInfo(message);

        message.setContent(Exception.class, ex);
        unwind(message);
        Exception ex2 = message.getContent(Exception.class);
        if (ex2 == null) {
            ex2 = ex;
        }

        FaultListener flogger = (FaultListener)
                message.getContextualProperty(FaultListener.class.getName());
        boolean useDefaultLogging = true;
        if (flogger != null) {
            useDefaultLogging = flogger.faultOccurred(ex2, description, message);
        }
        if (useDefaultLogging) {
            doDefaultLogging(message, ex2, description);
        }

        if (message.getExchange() != null && message.getContent(Exception.class) != null) {
            message.getExchange().put(Exception.class, ex2);
        }

        if (faultObserver != null && !isOneWay(message)) {
            // CXF-5629. when exchange is one way and robust, it becomes req-resp in order to
            // send the fault
            message.getExchange().setOneWay(false);
            faultObserver.onMessage(message);
        }
    }

    private String getServiceInfo(Message message) {
        StringBuilder description = new StringBuilder();
        if (message.getExchange() != null) {
            Exchange exchange = message.getExchange();
            Service service = exchange.getService();
            if (service != null) {
                description.append('\'');
                description.append(service.getName());
                BindingOperationInfo boi = exchange.getBindingOperationInfo();
                OperationInfo opInfo = boi != null ? boi.getOperationInfo() : null;
                if (opInfo != null) {
                    description.append('#').append(opInfo.getName());
                }
                description.append("\' ");
            }
        }
        return description.toString();
    }

    private void doDefaultLogging(Message message, Exception ex, String description) {
        FaultMode mode = message.get(FaultMode.class);
        if (mode == FaultMode.CHECKED_APPLICATION_FAULT) {
            if (isFineLogging) {
                LogUtils.log(LOG, Level.FINE,
                             "Application " + description
                             + "has thrown exception, unwinding now", ex);
            } else if (LOG.isLoggable(Level.INFO)) {
                Throwable t = ex;
                if (ex instanceof Fault
                    && ex.getCause() != null) {
                    t = ex.getCause();
                }

                LogUtils.log(LOG, Level.INFO,
                             "Application " + description
                             + "has thrown exception, unwinding now: "
                             + t.getClass().getName()
                             + ": " + ex.getMessage());
            }
        } else if (LOG.isLoggable(Level.WARNING)) {
            if (mode == FaultMode.UNCHECKED_APPLICATION_FAULT) {
                LogUtils.log(LOG, Level.WARNING,
                             "Application " + description
                             + "has thrown exception, unwinding now", ex);
            } else {
                LogUtils.log(LOG, Level.WARNING,
                             "Interceptor for " + description
                             + "has thrown exception, unwinding now", ex);
            }
        }
    }

    private boolean isOneWay(Message message) {
        return (message.getExchange() != null) && message.getExchange().isOneWay() && !isRobustOneWay(message);
    }

    private boolean isRobustOneWay(Message message) {
        return MessageUtils.getContextualBoolean(message, Message.ROBUST_ONEWAY, false);
    }

    /**
     * Intercept a message, invoking each phase's handlers in turn,
     * starting after the specified interceptor.
     *
     * @param message the message
     * @param startingAfterInterceptorID the id of the interceptor
     * @throws Exception
     */
    public synchronized boolean doInterceptStartingAfter(Message message,
                                                         String startingAfterInterceptorID) {
        updateIterator();
        while (state == State.EXECUTING && iterator.hasNext()) {
            PhaseInterceptor<? extends Message> currentInterceptor
                = (PhaseInterceptor<? extends Message>)iterator.next();
            if (currentInterceptor.getId().equals(startingAfterInterceptorID)) {
                break;
            }
        }
        return doIntercept(message);
    }

    /**
     * Intercept a message, invoking each phase's handlers in turn,
     * starting at the specified interceptor.
     *
     * @param message the message
     * @param startingAtInterceptorID the id of the interceptor
     * @throws Exception
     */
    public synchronized boolean doInterceptStartingAt(Message message,
                                                         String startingAtInterceptorID) {
        updateIterator();
        while (state == State.EXECUTING && iterator.hasNext()) {
            PhaseInterceptor<? extends Message> currentInterceptor
                = (PhaseInterceptor<? extends Message>)iterator.next();
            if (currentInterceptor.getId().equals(startingAtInterceptorID)) {
                iterator.previous();
                break;
            }
        }
        return doIntercept(message);
    }

    public synchronized void reset() {
        updateIterator();
        if (state == State.COMPLETE) {
            state = State.EXECUTING;
            iterator.reset();
        } else {
            iterator.reset();
        }
    }

    @SuppressWarnings("unchecked")
    public void unwind(Message message) {
        while (iterator.hasPrevious()) {
            Interceptor<Message> currentInterceptor = (Interceptor<Message>)iterator.previous();
            if (isFineLogging) {
                LOG.fine("Invoking handleFault on interceptor " + currentInterceptor);
            }
            try {
                currentInterceptor.handleFault(message);
            } catch (RuntimeException e) {
                LOG.log(Level.WARNING, "Exception in handleFault on interceptor " + currentInterceptor, e);
                throw e;
            } catch (Exception e) {
                LOG.log(Level.WARNING, "Exception in handleFault on interceptor " + currentInterceptor, e);
                throw new RuntimeException(e);
            }
        }
    }

    public void remove(Interceptor<? extends Message> i) {
        PhaseInterceptorIterator it = new PhaseInterceptorIterator(heads);
        while (it.hasNext()) {
            InterceptorHolder holder = it.nextInterceptorHolder();
            if (holder.interceptor == i) {
                remove(holder);
                return;
            }
        }
    }

    public synchronized void abort() {
        this.state = InterceptorChain.State.ABORTED;
    }

    public Iterator<Interceptor<? extends Message>> iterator() {
        return getIterator();
    }
    public ListIterator<Interceptor<? extends Message>> getIterator() {
        return new PhaseInterceptorIterator(heads);
    }

    private void remove(InterceptorHolder i) {
        if (i.prev != null) {
            i.prev.next = i.next;
        }
        if (i.next != null) {
            i.next.prev = i.prev;
        }
        int ph = i.phaseIdx;
        if (heads[ph] == i) {
            if (i.next != null
                && i.next.phaseIdx == ph) {
                heads[ph] = i.next;
            } else {
                heads[ph] = null;
                tails[ph] = null;
            }
        }
        if (tails[ph] == i) {
            if (i.prev != null
                && i.prev.phaseIdx == ph) {
                tails[ph] = i.prev;
            } else {
                heads[ph] = null;
                tails[ph] = null;
            }
        }
    }

    private void insertInterceptor(int phase, PhaseInterceptor<? extends Message> interc, boolean force) {
        InterceptorHolder ih = new InterceptorHolder(interc, phase);
        if (heads[phase] == null) {
            // no interceptors yet in this phase
            heads[phase] = ih;
            tails[phase] = ih;
            hasAfters[phase] = !interc.getAfter().isEmpty();

            int idx = phase - 1;
            while (idx >= 0) {
                if (tails[idx] != null) {
                    break;
                }
                --idx;
            }
            if (idx >= 0) {
                //found something before us, in an earlier phase
                ih.prev = tails[idx];
                ih.next = tails[idx].next;
                if (ih.next != null) {
                    ih.next.prev = ih;
                }
                tails[idx].next = ih;
            } else {
                //did not find something before us, try after
                idx = phase + 1;
                while (idx < heads.length) {
                    if (heads[idx] != null) {
                        break;
                    }
                    ++idx;
                }

                if (idx != heads.length) {
                    //found something after us
                    ih.next = heads[idx];
                    heads[idx].prev = ih;
                }
            }
        } else { // this phase already has interceptors attached

            // list of interceptors that the new interceptor should precede
            Set<String> beforeList = interc.getBefore();

            // list of interceptors that the new interceptor should be after
            Set<String> afterList = interc.getAfter();

            // firstBefore will hold the first interceptor of a given phase
            // that the interceptor to be added must precede
            InterceptorHolder firstBefore = null;

            // lastAfter will hold the last interceptor of a given phase
            // that the interceptor to be added must come after
            InterceptorHolder lastAfter = null;

            String id = interc.getId();
            if (hasAfters[phase] || !beforeList.isEmpty()) {

                InterceptorHolder ih2 = heads[phase];
                while (ih2 != tails[phase].next) {
                    PhaseInterceptor<? extends Message> cmp = ih2.interceptor;
                    String cmpId = cmp.getId();
                    if (cmpId != null && firstBefore == null
                        && (beforeList.contains(cmpId)
                            || cmp.getAfter().contains(id))) {
                        firstBefore = ih2;
                    }
                    if (cmp.getBefore().contains(id)
                        || (cmpId != null && afterList.contains(cmpId))) {
                        lastAfter = ih2;
                    }
                    if (!force && cmpId.equals(id)) {
                        // interceptor is already in chain
                        return;
                    }
                    ih2 = ih2.next;
                }
                if (lastAfter == null && beforeList.contains("*")) {
                    firstBefore = heads[phase];
                }
                
            } else if (!force) {
                // skip interceptor if already in chain
                InterceptorHolder ih2 = heads[phase];
                while (ih2 != tails[phase].next) {
                    if (ih2.interceptor.getId().equals(id)) {
                        return;
                    }
                    ih2 = ih2.next;
                }

            }
            hasAfters[phase] |= !afterList.isEmpty();

            if (firstBefore == null
                && lastAfter == null
                && !beforeList.isEmpty()
                && afterList.isEmpty()) {
                //if this interceptor has stuff it MUST be before,
                //but nothing it must be after, just
                //stick it at the beginning
                firstBefore = heads[phase];
            }

            if (firstBefore == null) {
                //just add new interceptor at the end
                ih.prev = tails[phase];
                ih.next = tails[phase].next;
                tails[phase].next = ih;

                if (ih.next != null) {
                    ih.next.prev = ih;
                }
                tails[phase] = ih;
            } else {
                ih.prev = firstBefore.prev;
                if (ih.prev != null) {
                    ih.prev.next = ih;
                }
                ih.next = firstBefore;
                firstBefore.prev = ih;

                if (heads[phase] == firstBefore) {
                    heads[phase] = ih;
                }
            }
        }
        if (iterator != null) {
            outputChainToLog(true);
        }
    }

    public String toString() {
        return toString("");
    }
    private String toString(String message) {
        StringBuilder chain = new StringBuilder(128);

        chain.append("Chain ")
            .append(super.toString())
            .append(message)
            .append(". Current flow:\n");

        for (int x = 0; x < phases.length; x++) {
            if (heads[x] != null) {
                chain.append("  ");
                printPhase(x, chain);
            }
        }
        return chain.toString();
    }
    private void printPhase(int ph, StringBuilder chain) {

        chain.append(phases[ph].getName())
            .append(" [");
        InterceptorHolder i = heads[ph];
        boolean first = true;
        while (i != tails[ph].next) {
            if (first) {
                first = false;
            } else {
                chain.append(", ");
            }
            String nm = i.interceptor.getClass().getSimpleName();
            if (StringUtils.isEmpty(nm)) {
                nm = i.interceptor.getId();
            }
            chain.append(nm);
            i = i.next;
        }
        chain.append("]\n");
    }

    private void outputChainToLog(boolean modified) {
        if (isFineLogging) {
            if (modified) {
                LOG.fine(toString(" was modified"));
            } else {
                LOG.fine(toString(" was created"));
            }
        }
    }

    public MessageObserver getFaultObserver() {
        return faultObserver;
    }

    public void setFaultObserver(MessageObserver faultObserver) {
        this.faultObserver = faultObserver;
    }

    static final class PhaseInterceptorIterator implements ListIterator<Interceptor<? extends Message>> {
        InterceptorHolder[] heads;
        InterceptorHolder prev;
        InterceptorHolder first;

        PhaseInterceptorIterator(InterceptorHolder[] h) {
            heads = h;
            first = findFirst();
        }

        public void reset() {
            prev = null;
            first = findFirst();
        }

        private InterceptorHolder findFirst() {
            for (int x = 0; x < heads.length; x++) {
                if (heads[x] != null) {
                    return heads[x];
                }
            }
            return null;
        }


        public boolean hasNext() {
            if (prev == null) {
                return first != null;
            }
            return prev.next != null;
        }

        public Interceptor<? extends Message> next() {
            if (prev == null) {
                if (first == null) {
                    throw new NoSuchElementException();
                }
                prev = first;
            } else {
                if (prev.next == null) {
                    throw new NoSuchElementException();
                }
                prev = prev.next;
            }
            return prev.interceptor;
        }
        public InterceptorHolder nextInterceptorHolder() {
            if (prev == null) {
                if (first == null) {
                    throw new NoSuchElementException();
                }
                prev = first;
            } else {
                if (prev.next == null) {
                    throw new NoSuchElementException();
                }
                prev = prev.next;
            }
            return prev;
        }

        public boolean hasPrevious() {
            return prev != null;
        }
        public Interceptor<? extends Message> previous() {
            if (prev == null) {
                throw new NoSuchElementException();
            }
            InterceptorHolder tmp = prev;
            prev = prev.prev;
            return tmp.interceptor;
        }

        public int nextIndex() {
            throw new UnsupportedOperationException();
        }
        public int previousIndex() {
            throw new UnsupportedOperationException();
        }
        public void add(Interceptor<? extends Message> o) {
            throw new UnsupportedOperationException();
        }
        public void set(Interceptor<? extends Message> o) {
            throw new UnsupportedOperationException();
        }
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }


    static final class InterceptorHolder {
        PhaseInterceptor<? extends Message> interceptor;
        InterceptorHolder next;
        InterceptorHolder prev;
        int phaseIdx;

        InterceptorHolder(PhaseInterceptor<? extends Message> i, int p) {
            interceptor = i;
            phaseIdx = p;
        }
        InterceptorHolder(InterceptorHolder p) {
            interceptor = p.interceptor;
            phaseIdx = p.phaseIdx;
        }
    }

}
