/*
 *  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.synapse.endpoints;

import org.apache.axis2.addressing.AddressingConstants;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.transport.passthru.PassThroughConstants;
import org.apache.synapse.transport.passthru.Pipe;
import org.apache.synapse.transport.passthru.util.RelayUtils;
import org.json.JSONObject;

/**
 * This class represents an endpoint with the EPR as the 'To' header of the message. It is
 * responsible for sending the message to this EPR, performing retries etc on failure and
 * using any QOS etc as specified
 */
public class DefaultEndpoint extends AbstractEndpoint {

    public void onFault(MessageContext synCtx) {
        boolean isRecursive = getParentEndpoint() instanceof FailoverEndpoint ||
                getParentEndpoint() instanceof LoadbalanceEndpoint;
        // For setting Car name (still for Proxy)
        logSetter();
        if (getContext().isMaxRetryLimitReached(isRecursive)) {
            getContext().onFailoverRetryLimit(isRecursive);
        } else {
            // is this really a fault or a timeout/connection close etc?
            if (isTimeout(synCtx)) {
                getContext().onTimeout();
            } else if (isSuspendFault(synCtx)) {
                getContext().onFault();
            }
        }

        // this should be an ignored error if we get here
        setErrorOnMessage(synCtx, null, null);
        super.onFault(synCtx);
    }

    public void onSuccess() {
        if (getContext() != null) {
            getContext().onSuccess();
        }
    }

    @Override
    protected void createJsonRepresentation() {
        endpointJson = new JSONObject();
        endpointJson.put(NAME_JSON_ATT, getName());
        endpointJson.put(TYPE_JSON_ATT, "Default Endpoint");
        endpointJson.put(CHILDREN_JSON_ATT, getEndpointChildrenAsJson(getChildren()));
        setAdvancedProperties();
    }

    public void send(MessageContext synCtx) {

        // For setting Car name (still for Proxy)
        logSetter();

        if (synCtx.getTo().isWSAddressingAnonymous()) {
            log.warn("'To' header was set to " + AddressingConstants.Final.WSA_ANONYMOUS_URL + ", Message will be " +
                    "passed to the fault sequence");
            informFailure(synCtx, SynapseConstants.ENDPOINT_ADDRESS_NONE_READY, "'To' header was set to " +
                    AddressingConstants.Final.WSA_ANONYMOUS_URL);
            return;
        }

    	org.apache.axis2.context.MessageContext messageContext =((Axis2MessageContext) synCtx).getAxis2MessageContext();
    	final Pipe pipe = (Pipe) messageContext.getProperty(PassThroughConstants.PASS_THROUGH_PIPE);
        if (pipe != null && !Boolean.TRUE.equals(messageContext.getProperty(PassThroughConstants.MESSAGE_BUILDER_INVOKED)) && messageContext.getProperty("To") == null) {
        	 try {
	            RelayUtils.buildMessage(((Axis2MessageContext) synCtx).getAxis2MessageContext(),false);
            } catch (Exception e) {
                 handleException("Error while building message", e, synCtx);
             }
        }
        if (getParentEndpoint() == null && !readyToSend()) {
            // if the this leaf endpoint is too a root endpoint and is in inactive
            informFailure(synCtx, SynapseConstants.ENDPOINT_ADDRESS_NONE_READY,
                    "Currently , Default endpoint : " + getContext());
        } else {
            super.send(synCtx);
        }
    }
}
