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

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axis2.AxisFault;
import org.apache.axis2.engine.AxisConfiguration;
import org.apache.axis2.util.PolicyUtil;
import org.apache.axis2.util.WSDL20Util;
import org.apache.axis2.util.WSDLSerializationUtil;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyComponent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class AxisBindingMessage extends AxisDescription {

    private String name;

    private String direction;

    private Map<String, Object> options;

    private AxisMessage axisMessage;

    // Used to indicate whether this message is a fault or not. Needed for the
    // WSDL 2.0 serializer
    private boolean fault = false;

    private volatile Policy effectivePolicy = null;
    private volatile OpaqueInstant lastPolicyCalculatedTime = null;

    public boolean isFault() {
        return fault;
    }

    public void setFault(boolean fault) {
        this.fault = fault;
    }

    public String getName() {
        return name;
    }

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

    public AxisMessage getAxisMessage() {
        return axisMessage;
    }

    public void setAxisMessage(AxisMessage axisMessage) {
        this.axisMessage = axisMessage;
    }

    public String getDirection() {
        return direction;
    }

    public void setDirection(String direction) {
        this.direction = direction;
    }

    public AxisBindingMessage() {
        options = new HashMap<String, Object>();
    }

    public void setProperty(String name, Object value) {
        options.put(name, value);
    }

    /**
     * @param name
     *            name of the property to search for
     * @return the value of the property, or null if the property is not found
     */
    public Object getProperty(String name) {
        Object obj = options.get(name);
        if (obj != null) {
            return obj;
        }

        return null;
    }

    public Object getKey() {
        return null; // To change body of implemented methods use File |
        // Settings | File Templates.
    }

    public void engageModule(AxisModule axisModule) throws AxisFault {
        throw new UnsupportedOperationException("Sorry we do not support this");
    }

    public boolean isEngaged(String moduleName) {
        throw new UnsupportedOperationException(
                "axisMessage.isEngaged() is not supported");

    }

    /**
     * Generates the bindingMessage element (can be input, output, infault or
     * outfault)
     * 
     * @param tns -
     *            The targetnamespace
     * @param wsoap -
     *            The SOAP namespace (WSDL 2.0)
     * @param whttp -
     *            The HTTP namespace (WSDL 2.0)
     * @param nameSpaceMap -
     *            The namespacemap of the service
     * @return The generated bindingMessage element
     */
    public OMElement toWSDL20(OMNamespace wsdl, OMNamespace tns,
            OMNamespace wsoap, OMNamespace whttp, Map<String, String> nameSpaceMap) {
        String property;
        ArrayList list;
        OMFactory omFactory = OMAbstractFactory.getOMFactory();
        OMElement bindingMessageElement;

        // If this is a fault, create a fault element and add fault specific
        // properties
        if (this.isFault()) {
            if (this.getParent() instanceof AxisBinding) {
                bindingMessageElement = omFactory.createOMElement(
                        WSDL2Constants.FAULT_LOCAL_NAME, wsdl);
            } else if (WSDLConstants.WSDL_MESSAGE_DIRECTION_IN.equals(this
                    .getDirection())) {
                bindingMessageElement = omFactory.createOMElement(
                        WSDL2Constants.IN_FAULT_LOCAL_NAME, wsdl);
            } else {
                bindingMessageElement = omFactory.createOMElement(
                        WSDL2Constants.OUT_FAULT_LOCAL_NAME, wsdl);
            }
            bindingMessageElement.addAttribute(omFactory.createOMAttribute(
                    WSDL2Constants.ATTRIBUTE_REF, null, tns.getPrefix() + ":"
                            + this.name));

            WSDL20Util.extractWSDL20SoapFaultInfo(options,
                    bindingMessageElement, omFactory, wsoap);

            Integer code = (Integer) this.options
                    .get(WSDL2Constants.ATTR_WHTTP_CODE);
            if (code != null) {
                bindingMessageElement.addAttribute(omFactory.createOMAttribute(
                        WSDL2Constants.ATTRIBUTE_CODE, whttp, code.toString()));
            }

            // Checks whether the message is an input message
        } else if (WSDLConstants.WSDL_MESSAGE_DIRECTION_IN.equals(this
                .getDirection())) {
            bindingMessageElement = omFactory.createOMElement(
                    WSDL2Constants.IN_PUT_LOCAL_NAME, wsdl);

            // Message should be an output message
        } else {
            bindingMessageElement = omFactory.createOMElement(
                    WSDL2Constants.OUT_PUT_LOCAL_NAME, wsdl);
        }

        // Populate common properties
        property = (String) this.options
                .get(WSDL2Constants.ATTR_WHTTP_CONTENT_ENCODING);
        if (property != null) {
            bindingMessageElement
                    .addAttribute(omFactory.createOMAttribute(
                            WSDL2Constants.ATTRIBUTE_CONTENT_ENCODING, whttp,
                            property));
        }
        list = (ArrayList) this.options.get(WSDL2Constants.ATTR_WHTTP_HEADER);
        if (list != null && list.size() > 0) {
            WSDLSerializationUtil.addHTTPHeaderElements(omFactory, list, whttp,
                    bindingMessageElement, nameSpaceMap);
        }
        list = (ArrayList) this.options.get(WSDL2Constants.ATTR_WSOAP_HEADER);
        if (list != null && list.size() > 0) {
            WSDLSerializationUtil.addSOAPHeaderElements(omFactory, list, wsoap,
                    bindingMessageElement, nameSpaceMap);
        }
        list = (ArrayList) this.options.get(WSDL2Constants.ATTR_WSOAP_MODULE);
        if (list != null && list.size() > 0) {
            WSDLSerializationUtil.addSOAPModuleElements(omFactory, list, wsoap,
                    bindingMessageElement);
        }
        WSDLSerializationUtil.addWSDLDocumentationElement(this,
                bindingMessageElement, omFactory, wsdl);
        WSDLSerializationUtil.addPoliciesAsExtensibleElement(this,
                bindingMessageElement);
        return bindingMessageElement;
    }

    public AxisBindingOperation getAxisBindingOperation() {
        return (AxisBindingOperation) parent;
    }

    public Policy getEffectivePolicy() {
        if (lastPolicyCalculatedTime == null || isPolicyUpdated()) {
            synchronized (this) {
                if (lastPolicyCalculatedTime == null || isPolicyUpdated()) {
                    effectivePolicy = calculateEffectivePolicy();
                    lastPolicyCalculatedTime = new OpaqueInstant();
                }
            }
        }
        return effectivePolicy;
    }

    public Policy calculateEffectivePolicy() {
        PolicySubject policySubject = null;
        Collection<PolicyComponent> policyList = new ArrayList<PolicyComponent>();

        // AxisBindingMessage
        policySubject = getPolicySubject();
        policyList.addAll(policySubject.getAttachedPolicyComponents());

        // AxisBindingOperation policies
        AxisBindingOperation axisBindingOperation = getAxisBindingOperation();
        if (axisBindingOperation != null) {
            policyList.addAll(axisBindingOperation.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisBinding
        AxisBinding axisBinding = (axisBindingOperation == null) ? null
                : axisBindingOperation.getAxisBinding();
        if (axisBinding != null) {
            policyList.addAll(axisBinding.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisEndpoint
        AxisEndpoint axisEndpoint = (axisBinding == null) ? null : axisBinding
                .getAxisEndpoint();
        if (axisEndpoint != null) {
            policyList.addAll(axisEndpoint.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisMessage
        if (axisMessage != null) {
            policyList.addAll(axisMessage.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisOperation
        AxisOperation axisOperation = (axisMessage == null) ? null
                : axisMessage.getAxisOperation();
        if (axisOperation != null) {
            policyList.addAll(axisOperation.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisService
        AxisService axisService = (axisOperation == null) ? null
                : axisOperation.getAxisService();
        if (axisService != null) {
            policyList.addAll(axisService.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        // AxisConfiguration
        AxisConfiguration axisConfiguration = (axisService == null) ? null
                : axisService.getAxisConfiguration();
        if (axisConfiguration != null) {
            policyList.addAll(axisConfiguration.getPolicySubject()
                    .getAttachedPolicyComponents());
        }

        return PolicyUtil.getMergedPolicy(policyList, axisService);
    }
    
    private boolean isPolicyUpdated() {
        if (getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisBindingOperation
        AxisBindingOperation axisBindingOperation = getAxisBindingOperation();
        if (axisBindingOperation != null
                && axisBindingOperation.getPolicySubject().getLastUpdatedTime()
                        .after(lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisBinding
        AxisBinding axisBinding = (axisBindingOperation == null) ? null
                : axisBindingOperation.getAxisBinding();
        if (axisBinding != null
                && axisBinding.getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisEndpoint
        AxisEndpoint axisEndpoint = (axisBinding == null) ? null : axisBinding
                .getAxisEndpoint();
        if (axisEndpoint != null
                && axisEndpoint.getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisMessage
        if (axisMessage != null
                && axisMessage.getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisOperation
        AxisOperation axisOperation = (axisMessage == null) ? null
                : axisMessage.getAxisOperation();
        if (axisOperation != null
                && axisOperation.getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisService
        AxisService axisService = (axisOperation == null) ? null
                : axisOperation.getAxisService();
        if (axisService != null
                && axisService.getPolicySubject().getLastUpdatedTime().after(
                lastPolicyCalculatedTime)) {
            return true;
        }
        // AxisConfiguration
        AxisConfiguration axisConfiguration = (axisService == null) ? null
                : axisService.getAxisConfiguration();
        if (axisConfiguration != null
                && axisConfiguration.getPolicySubject().getLastUpdatedTime()
                        .after(lastPolicyCalculatedTime)) {
            return true;
        }
        return false;
    }
    
    @Override
    public void applyPolicy() throws AxisFault {
        getAxisMessage().applyPolicy();
    }
}
