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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.axis2.Axis2TestBase;
import org.apache.ode.axis2.JettyWrapper;
import static org.testng.AssertJUnit.assertTrue;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.util.concurrent.CountDownLatch;

/**
 * <p/>
 * This unit test passes an integer to a BPEL. Then the BPEL invokes the 6 operations of Arithmetics.wsdl.
 * These operations are set up to use the various Http binding configurations.
 * <p/>
 * From a "business" standpoint:<br/>
 * Let N be the input number, stored in the testRequest1.soap file<br/>
 * This test will compute the Sum of the first (N + 5) positive integers.
 * <p/>
 * If N=10, the expected result is 15*(15+1)/2 = 120
 *
 * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
 */
public class HttpBindingTest extends Axis2TestBase {

    private static final Logger log = LoggerFactory.getLogger(HttpBindingTest.class);

    protected JettyWrapper jettyWrapper;


  @BeforeMethod
    protected void setUp() throws Exception {
        super.setUp();
      jettyWrapper = new JettyWrapper(getTestPort(1));
      jettyWrapper.start();
  }

    @AfterMethod
    protected void tearDown() throws Exception {
        jettyWrapper.stop();
        super.tearDown();
    }

    @Test(dataProvider="configs")
    public void testHttpBinding() throws Exception {
        String bundleName = "TestHttpBinding";
        // deploy the required service
        if (!server.isDeployed(bundleName)) server.deployProcess(bundleName);
        try {
            String response = sendRequestFile("http://localhost:8888/processes/helloWorld",
                    bundleName, "testRequest.soap");
            if (log.isDebugEnabled()) log.debug(response);
            int valueInSoapRequest = 100;
            int n = 5 + valueInSoapRequest;
            String expectedResult = String.valueOf(n * (n + 1) / 2);
            assertTrue("Expected Result: " + expectedResult + ". Answer was " + response, response.indexOf(expectedResult) >= 0);
        } finally {
            server.undeployProcess(bundleName);
        }
    }

    @Test(dataProvider="configs")
    public void testHttpBindingExt_GET() throws Exception {
        String bundleName = "TestHttpBindingExt_GET";
        executeBundle(bundleName);

    }

    @Test(dataProvider="configs")
    public void testHttpBindingExt_DELETE() throws Exception {
        String bundleName = "TestHttpBindingExt_DELETE";
        executeBundle(bundleName);
    }

    @Test(dataProvider="configs")
    public void testHttpBindingExt_POST() throws Exception {
        String bundleName = "TestHttpBindingExt_POST";
        executeBundle(bundleName);
    }

    @Test(dataProvider="configs")
    public void testHttpBindingExt_PUT() throws Exception {
        String bundleName = "TestHttpBindingExt_PUT";
        executeBundle(bundleName);
    }

    private void executeBundle(String bundleName) throws InterruptedException {
        // wait for jetty to be ready
        // clean up everything first
        if (server.isDeployed(bundleName)) server.undeployProcess(bundleName);

        // then deploy the required service
        server.deployProcess(bundleName);
        try {
            String response = sendRequestFile("http://localhost:8888/processes/helloWorld", bundleName, "testRequest.soap");
            System.out.println("Test Response Received: "+response);
            if (log.isDebugEnabled()) log.debug("Test Response Received: "+response);
            assertTrue("Test failed. Response is:"+response, response.indexOf("What a success!") >= 0);
        } finally {
            server.undeployProcess(bundleName);
        }
    }
}
