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

import junit.framework.TestCase;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.RolePlayer;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.impl.builder.StAXSOAPModelBuilder;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.addressing.RelatesTo;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.handlers.util.TestUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

public abstract class AddressingInHandlerTestBase extends TestCase {
    private static Log log = LogFactory.getLog(AddressingInHandlerTestBase.class);
    AddressingInHandler inHandler;
    String addressingNamespace;
    TestUtil testUtil = new TestUtil();
    String testFileName = "soapmessage.xml";

    String versionDirectory;

    private String action = "http://ws.apache.org/tests/action";
    private String messageID = "uuid:920C5190-0B8F-11D9-8CED-F22EDEEBF7E5";
    String fromAddress;
    String secondRelationshipType;
    private String faultAddress = "http://example.com/fabrikam/fault";
    private String replyAddress = "http://example.com/fabrikam/acct";
    private String toAddress = "http://localhost:8081/axis/services/BankPort";

    /** @param testName  */
    public AddressingInHandlerTestBase(String testName) {
        super(testName);
    }

    protected void basicExtractAddressingInformationFromHeaders(String testMessagePath,
                                                                MessageContext mc)
            throws Exception {
        StAXSOAPModelBuilder omBuilder = testUtil.getOMBuilder(testMessagePath);
        SOAPEnvelope envelope = (SOAPEnvelope) omBuilder.getDocumentElement();
        mc.setEnvelope(envelope);
        inHandler.invoke(mc);
    }

    protected Options extractAddressingInformationFromHeaders(RolePlayer rolePlayer) throws Exception{
            String testfile = "valid-messages/" + versionDirectory + "/" + testFileName;

            MessageContext mc = new MessageContext();
            mc.setConfigurationContext(ConfigurationContextFactory.createDefaultConfigurationContext());
            if(rolePlayer != null){
            	mc.getConfigurationContext().getAxisConfiguration().addParameter(Constants.SOAP_ROLE_PLAYER_PARAMETER, rolePlayer);
            }
            basicExtractAddressingInformationFromHeaders(testfile, mc);

            Options options = mc.getOptions();

            if (options == null) {
                fail("Addressing Information Headers have not been retrieved properly");
            }
            assertEquals("action header is not correct", action, options.getAction());
            assertActionHasExtensibilityAttribute(mc);
            assertEquals("message id header is not correct",
                         options.getMessageId().trim(),
                         messageID.trim());
            assertMessageIDHasExtensibilityAttribute(mc);

            assertFullFromEPR(options.getFrom());
            assertFullFaultEPR(options.getFaultTo());
            assertFullReplyToEPR(options.getReplyTo());

            assertRelationships(options);

            return options;
    }

    private void testExtractAddressingInformationFromHeadersInvalidCardinality(String headerName) {
        String testfile = "invalid-cardinality-messages/" + versionDirectory +
                "/invalidCardinality" + headerName + "Message.xml";
        try {
            MessageContext mc = new MessageContext();
            mc.setConfigurationContext(ConfigurationContextFactory.createDefaultConfigurationContext());
            try {
                basicExtractAddressingInformationFromHeaders(testfile, mc);
                fail("An AxisFault should have been thrown due to 2 wsa:" + headerName +
                        " headers.");
            } catch (AxisFault af) {
                if (headerName.equals(AddressingConstants.WSA_REPLY_TO)) {
                    assertNull("No ReplyTo should be set on the MessageContext", mc.getReplyTo());
                } else {
                    assertReplyToEPR(mc.getReplyTo());
                }

                if (headerName.equals(AddressingConstants.WSA_FAULT_TO)) {
                    assertNull("No FaultTo should be set on the MessageContext", mc.getFaultTo());
                } else {
                    assertFaultEPR(mc.getFaultTo());
                }

                if (headerName.equals(AddressingConstants.WSA_ACTION)) {
                    assertNull("No Action should be set on the MessageContext", mc.getWSAAction());
                } else {
                    assertEquals("WSAAction property is not correct", mc.getWSAAction(), action);
                }

                if (headerName.equals(AddressingConstants.WSA_MESSAGE_ID)) {
                    assertNull("No MessageID should be set on the MessageContext",
                               mc.getMessageID());
                } else {
                    assertEquals("MessageID property is not correct", mc.getMessageID().trim(),
                                 messageID.trim());
                }

                if (headerName.equals(AddressingConstants.WSA_FROM)) {
                    assertNull("No From should be set on the MessageContext", mc.getFrom());
                } else {
                    assertFromEPR(mc.getFrom());
                }

                if (headerName.equals(AddressingConstants.WSA_TO)) {
                    assertNull("No To should be set on the MessageContext", mc.getTo());
                } else {
                    assertToEPR(mc.getTo());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getMessage());
            fail(" An Exception has occured " + e.getMessage());
        }
    }

    protected Options testMessageWithOmittedHeaders(String testName) throws Exception {
        String testfile =
                "omitted-header-messages/" + versionDirectory + "/" + testName + "Message.xml";

        MessageContext mc = new MessageContext();
        ConfigurationContext cc = ConfigurationContextFactory.createDefaultConfigurationContext();
        mc.setConfigurationContext(cc);
        basicExtractAddressingInformationFromHeaders(testfile, mc);

        return mc.getOptions();
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityReplyTo() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(
                AddressingConstants.WSA_REPLY_TO);
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityFaultTo() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(
                AddressingConstants.WSA_FAULT_TO);
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityAction() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(
                AddressingConstants.WSA_ACTION);
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityMessageID() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(
                AddressingConstants.WSA_MESSAGE_ID);
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityFrom() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(AddressingConstants.WSA_FROM);
    }

    public void testExtractAddressingInformationFromHeadersInvalidCardinalityTo() {
        testExtractAddressingInformationFromHeadersInvalidCardinality(AddressingConstants.WSA_TO);
    }

    private void assertFromEPR(EndpointReference fromEPR) {
        assertEquals("Address in From EPR is not valid",
                     fromEPR.getAddress().trim(),
                     fromAddress.trim());
    }

    private void assertFaultEPR(EndpointReference faultEPR) {
        assertEquals("Address in FaultTo EPR is not valid",
                     faultEPR.getAddress().trim(),
                     faultAddress.trim());
    }

    private void assertReplyToEPR(EndpointReference replyEPR) {
        assertEquals("Address in ReplytTo EPR is not valid",
                     replyEPR.getAddress().trim(),
                     replyAddress.trim());
    }

    private void assertToEPR(EndpointReference toEPR) {
        System.out.println(toEPR);
        assertEquals("Address in To EPR is not valid",
                     toEPR.getAddress().trim(),
                     toAddress.trim());
        assertEPRAddressHasExtensibilityAttribute(toEPR);
    }

    private void assertFullFromEPR(EndpointReference fromEPR) {
        assertEquals("Address in From EPR is not valid",
                     fromEPR.getAddress().trim(),
                     fromAddress.trim());
        assertEPRHasExtensibilityAttribute(fromEPR);
        assertEPRHasCorrectReferenceParameters(fromEPR);
        assertEPRHasCorrectExtensibilityElements(fromEPR);
    }

    private void assertFullFaultEPR(EndpointReference faultEPR) {
        assertEquals("Address in FaultTo EPR is not valid",
                     faultEPR.getAddress().trim(),
                     faultAddress.trim());
        assertEPRHasExtensibilityAttribute(faultEPR);
        assertEPRHasCorrectReferenceParameters(faultEPR);
        assertEPRHasCorrectExtensibilityElements(faultEPR);
    }

    private void assertFullReplyToEPR(EndpointReference replyEPR) {
        assertEquals("Address in ReplytTo EPR is not valid",
                     replyEPR.getAddress().trim(),
                     replyAddress.trim());
        assertEPRHasExtensibilityAttribute(replyEPR);
        assertEPRHasCorrectReferenceParameters(replyEPR);
        assertEPRHasCorrectExtensibilityElements(replyEPR);
    }

    private void assertEPRHasCorrectReferenceParameters(EndpointReference epr) {
        //<wsa:ReferenceParameters>
        //  <fabrikam:CustomerKey>123456789</fabrikam:CustomerKey>
        //  <fabrikam:ShoppingCart>ABCDEFG</fabrikam:ShoppingCart>
        //</wsa:ReferenceParameters>
        Map referenceParameters = epr.getAllReferenceParameters();
        if (referenceParameters != null) {
            OMElement refparm1 = (OMElement)referenceParameters
                    .get(new QName("http://example.com/fabrikam", "CustomerKey"));
            assertNotNull(refparm1);
            assertEquals("ReferenceParameter value incorrect.", refparm1.getText(), "123456789");

            OMElement refparm2 = (OMElement)referenceParameters
                    .get(new QName("http://example.com/fabrikam", "ShoppingCart"));
            assertNotNull(refparm2);
            assertEquals("ReferenceParameter value incorrect.", refparm2.getText(), "ABCDEFG");
        } else {
            fail("No ReferenceParameters found in EPR");
        }
    }

    private void assertActionHasExtensibilityAttribute(MessageContext mc) {
        boolean attributeFound = false;
        ArrayList attributes = (ArrayList)mc.getProperty(AddressingConstants.ACTION_ATTRIBUTES);
        if (attributes != null) {
            Iterator iter = attributes.iterator();
            while (iter.hasNext()) {
                OMAttribute oa = (OMAttribute)iter.next();
                if (oa.getLocalName().equals("AttrExt")) {
                    attributeFound = true;
                    assertEquals("Attribute value incorrectly deserialised", oa.getAttributeValue(),
                                 "123456789");
                }
            }
        }
        assertTrue("Extensibility attribute not found on Action", attributeFound);
    }

    private void assertMessageIDHasExtensibilityAttribute(MessageContext mc) {
        boolean attributeFound = false;
        ArrayList attributes = (ArrayList)mc.getProperty(AddressingConstants.MESSAGEID_ATTRIBUTES);
        if (attributes != null) {
            Iterator iter = attributes.iterator();
            while (iter.hasNext()) {
                OMAttribute oa = (OMAttribute)iter.next();
                if (oa.getLocalName().equals("AttrExt")) {
                    attributeFound = true;
                    assertEquals("Attribute value incorrectly deserialised", oa.getAttributeValue(),
                                 "123456789");
                }
            }
        }
        assertTrue("Extensibility attribute not found on MessageID", attributeFound);
    }

    private void assertRelatesToHasExtensibilityAttribute(RelatesTo rt) {
        boolean attributeFound = false;
        ArrayList attributes = rt.getExtensibilityAttributes();
        if (attributes != null) {
            Iterator iter = attributes.iterator();
            while (iter.hasNext()) {
                OMAttribute oa = (OMAttribute)iter.next();
                if (oa.getLocalName().equals("AttrExt")) {
                    attributeFound = true;
                    assertEquals("Attribute value incorrectly deserialised", oa.getAttributeValue(),
                                 "123456789");
                }
            }
        }
        assertTrue("Extensibility attribute not found on RelatesTo", attributeFound);
    }

    private void assertEPRAddressHasExtensibilityAttribute(EndpointReference epr) {
        boolean attributeFound = false;
        ArrayList attributes = epr.getAddressAttributes();
        if (attributes != null) {
            Iterator iter = attributes.iterator();
            while (iter.hasNext()) {
                OMAttribute oa = (OMAttribute)iter.next();
                if (oa.getLocalName().equals("AttrExt")) {
                    attributeFound = true;
                    assertEquals("Attribute value incorrectly deserialised", oa.getAttributeValue(),
                                 "123456789");
                }
            }
        }
        assertTrue("Extensibility attribute not found on EPR Address", attributeFound);
    }

    private void assertEPRHasExtensibilityAttribute(EndpointReference epr) {
        boolean attributeFound = false;
        ArrayList attributes = epr.getAttributes();
        if (attributes != null) {
            Iterator iter = attributes.iterator();
            while (iter.hasNext()) {
                OMAttribute oa = (OMAttribute)iter.next();
                if (oa.getLocalName().equals("AttrExt")) {
                    attributeFound = true;
                    assertEquals("Attribute value incorrectly deserialised", oa.getAttributeValue(),
                                 "123456789");
                }
            }
        }
        assertTrue("Extensibility attribute not found on EPR", attributeFound);
    }

    private void assertEPRHasCorrectExtensibilityElements(EndpointReference epr) {
        ArrayList eelements = epr.getExtensibleElements();
        if (eelements != null) {
            OMElement ee = (OMElement)eelements.get(0);
            assertEquals(ee.getQName(),
                         new QName("http://ws.apache.org/namespaces/axis2", "EPRExt"));
            assertEquals(ee.getText(), "123456789");
            assertEquals(ee.getAttributeValue(
                    new QName("http://ws.apache.org/namespaces/axis2", "AttrExt")), "123456789");
        } else {
            fail("No Extensibility Elements found in EPR");
        }
    }

    private void assertRelationships(Options options) {
        assertNotNull(options.getRelatesTo());
        assertRelatesToHasExtensibilityAttribute(options.getRelatesTo());
        assertEquals(options.getRelatesTo().getValue(), "http://some.previous.message");
        assertEquals(options.getRelatesTo(secondRelationshipType).getValue(),
                     "http://identifier.of.other.message/");
    }
}
