/*******************************************************************************
 * Copyright (c) 2014, 2019 Raymond Augé and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Raymond Augé <raymond.auge@liferay.com> - initial implementation
 ******************************************************************************/

package org.eclipse.equinox.http.servlet.testbase;

import static org.junit.Assert.assertNotNull;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.equinox.http.jetty.JettyConstants;
import org.eclipse.equinox.http.servlet.context.ContextPathCustomizer;
import org.eclipse.equinox.http.servlet.tests.bundle.BundleAdvisor;
import org.eclipse.equinox.http.servlet.tests.bundle.BundleInstaller;
import org.eclipse.equinox.http.servlet.tests.util.ServletRequestAdvisor;
import org.junit.After;
import org.junit.Before;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.service.http.runtime.dto.ErrorPageDTO;
import org.osgi.service.http.runtime.dto.FailedErrorPageDTO;
import org.osgi.service.http.runtime.dto.FailedFilterDTO;
import org.osgi.service.http.runtime.dto.FailedResourceDTO;
import org.osgi.service.http.runtime.dto.FailedServletContextDTO;
import org.osgi.service.http.runtime.dto.FailedServletDTO;
import org.osgi.service.http.runtime.dto.FilterDTO;
import org.osgi.service.http.runtime.dto.RequestInfoDTO;
import org.osgi.service.http.runtime.dto.ResourceDTO;
import org.osgi.service.http.runtime.dto.ServletContextDTO;
import org.osgi.service.http.runtime.dto.ServletDTO;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.util.tracker.ServiceTracker;

public class BaseTest {

	public static final String	DEFAULT	= HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME;

	@Before
	public void setUp() throws Exception {
		// Quiet logging for tests
		System.setProperty("/.LEVEL", "OFF");
		System.setProperty("org.eclipse.jetty.server.LEVEL", "OFF");
		System.setProperty("org.eclipse.jetty.servlet.LEVEL", "OFF");
		System.setProperty("org.osgi.service.http.port", "0");
		System.setProperty("org.eclipse.equinox.http.jetty.context.sessioninactiveinterval", "1");
		System.setProperty("org.eclipse.equinox.http.jetty.housekeeper.interval", "10");
		BundleContext bundleContext = getBundleContext();
		installer = new BundleInstaller(TEST_BUNDLES_BINARY_DIRECTORY, bundleContext);
		advisor = new BundleAdvisor(bundleContext);
		stopJetty();
		startBundles();
		runtimeTracker = new ServiceTracker<>(bundleContext, HttpServiceRuntime.class, null);
		runtimeTracker.open();
		runtimeTracker.waitForService(100);
		startJetty();
	}

	@After
	public void tearDown() throws Exception {
		runtimeTracker.close();
		stopBundles();
		requestAdvisor = null;
		advisor = null;
		try {
			installer.shutdown();
		} finally {
			installer = null;
		}

		for (ServiceRegistration<? extends Object> serviceRegistration : registrations) {
			try {
				serviceRegistration.unregister();
			}
			catch (Exception e) {
				// ignore
			}
		}
		registrations.clear();
	}

	protected String doRequest(String action, Map<String, String> params) throws IOException {
		return doRequestGetResponse(action, params).get("responseBody").get(0);
	}

	protected Map<String, List<String>> doRequestGetResponse(String action, Map<String, String> params) throws IOException {
		StringBuilder requestInfo = new StringBuilder(PROTOTYPE);
		requestInfo.append(action);
		if (!params.isEmpty()) {
			boolean firstParam = true;
			for (Map.Entry<String, String> param : params.entrySet()) {
				if (firstParam) {
					requestInfo.append('?');
					firstParam = false;
				} else {
					requestInfo.append('&');
				}
				requestInfo.append(param.getKey());
				requestInfo.append('=');
				requestInfo.append(param.getValue());
			}
		}
		return requestAdvisor.request(requestInfo.toString(), null);
	}

	protected BundleContext getBundleContext() {
		return FrameworkUtil.getBundle(BaseTest.class).getBundleContext();
	}

	protected String getContextPath() {
		return getJettyProperty("context.path", "");
	}

	protected HttpService getHttpService() {
		ServiceReference<HttpService> serviceReference = getBundleContext().getServiceReference(HttpService.class);
		return getBundleContext().getService(serviceReference);
	}

	protected String getJettyProperty(String key, String defaultValue) {
		String qualifiedKey = JETTY_PROPERTY_PREFIX + key;
		String value = getProperty(qualifiedKey);
		if (value == null) {
			value = defaultValue;
		}
		return value;
	}

	protected void setJettyProperty(String key, String value) {
		String qualifiedKey = JETTY_PROPERTY_PREFIX + key;
		System.setProperty(qualifiedKey, value);
	}

	protected String getPort() {
		String defaultPort = getProperty(OSGI_HTTP_PORT_PROPERTY);
		if (defaultPort == null) {
			defaultPort = "80";
		}
		return getJettyProperty("port", defaultPort);
	}

	protected String getProperty(String key) {
		BundleContext bundleContext = getBundleContext();
		String value = bundleContext.getProperty(key);
		return value;
	}

	protected List<String> getStringPlus(String key, ServiceReference<?> ref) {
		Object property = ref.getProperty(key);
		if (String.class.isInstance(property)) {
			return Collections.singletonList((String)property);
		}
		else if (String[].class.isInstance(property)) {
			return Arrays.asList((String[])property);
		}
		else if (Collection.class.isInstance(property)) {
			List<String> list = new ArrayList<String>();
			for (@SuppressWarnings("rawtypes")
				Iterator i = ((Collection)property).iterator(); i.hasNext();) {

				Object o = i.next();
				if (String.class.isInstance(o)) {
					list.add((String)o);
				}
			}
			return list;
		}
		return Collections.emptyList();
	}

	protected Bundle installBundle(String bundle) throws BundleException {
		return installer.installBundle(bundle);
	}

	protected void startBundles() throws BundleException {
	}

	protected void startJetty() throws Exception {
		advisor.startBundle(EQUINOX_JETTY_BUNDLE);
		ServiceReference<HttpServiceRuntime> runtimeReference = runtimeTracker.getServiceReference();
		List<String> endpoints = getStringPlus(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT, runtimeReference);
		String port = getPort();
		if (port.equals("0") && !endpoints.isEmpty()) {
			for (String endpoint : endpoints) {
				if (endpoint.startsWith("http://")) {
					port = String.valueOf(new URL(endpoint).getPort());
					break;
				}
			}
			if (port.equals("-1")) {
				port = "80";
			}
		}
		String contextPath = getContextPath();
		requestAdvisor = new ServletRequestAdvisor(port, contextPath);
	}

	protected void startJettyWithSSL(String port, String ksPath, String ksPassword, String keyPassword) throws Exception {
		if(port == null) {
			throw new IllegalArgumentException("Port cannot be null");
		}
		if (ksPath == null) {
			throw new IllegalArgumentException("Keystore path  cannot be null");
		}
		setJettyProperty(JettyConstants.HTTP_ENABLED, "false");
		setJettyProperty(JettyConstants.HTTPS_ENABLED, "true");

		setJettyProperty(JettyConstants.HTTPS_PORT, port);

		setJettyProperty(JettyConstants.SSL_KEYSTORE, ksPath);

		if(ksPassword != null) {
			setJettyProperty(JettyConstants.SSL_PASSWORD, ksPassword);
		}
		if(keyPassword != null) {
			setJettyProperty(JettyConstants.SSL_KEYPASSWORD, keyPassword);
		}

		advisor.startBundle(EQUINOX_JETTY_BUNDLE);
		String contextPath = getContextPath();
		requestAdvisor = new ServletRequestAdvisor(port, contextPath, ksPath, ksPassword);
	}

	protected void stopBundles() throws BundleException {
	}

	protected void stopJetty() throws BundleException {
		advisor.stopBundle(EQUINOX_JETTY_BUNDLE);
	}

	protected void stopJettyWithSSL() throws BundleException {
		advisor.stopBundle(EQUINOX_JETTY_BUNDLE);
		setJettyProperty(JettyConstants.HTTP_ENABLED, "true");
		setJettyProperty(JettyConstants.HTTPS_ENABLED, "false");
	}

	protected void uninstallBundle(Bundle bundle) throws BundleException {
		installer.uninstallBundle(bundle);
	}

	protected void write(OutputStream outputStream, String string) throws IOException {
		outputStream.write(string.getBytes(StandardCharsets.UTF_8));
	}

	protected FailedServletDTO getFailedServletDTOByName(String name) {
		for (FailedServletDTO failedServletDTO : getFailedServletDTOs()) {
			if (name.equals(failedServletDTO.name)) {
				return failedServletDTO;
			}
		}

		return null;
	}

	protected FailedServletDTO[] getFailedServletDTOs() {
		HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime();

		return httpServiceRuntime.getRuntimeDTO().failedServletDTOs;
	}

	protected HttpServiceRuntime getHttpServiceRuntime() {
		ServiceReference<HttpServiceRuntime> serviceReference =
				getBundleContext().getServiceReference(HttpServiceRuntime.class);

		assertNotNull(serviceReference);

		return getBundleContext().getService(serviceReference);
	}

	protected long getServiceId(ServiceRegistration<?> sr) {
		return (Long) sr.getReference().getProperty(Constants.SERVICE_ID);
	}

	protected RequestInfoDTO calculateRequestInfoDTO(String string) {
		HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime();

		return httpServiceRuntime.calculateRequestInfoDTO(string);
	}

	protected ServletDTO getServletDTOByName(String context, String name) {
		ServletContextDTO servletContextDTO = getServletContextDTOByName(context);

		if (servletContextDTO == null) {
			return null;
		}

		for (ServletDTO servletDTO : servletContextDTO.servletDTOs) {
			if (name.equals(servletDTO.name)) {
				return servletDTO;
			}
		}

		return null;
	}

	protected ServletContextDTO getServletContextDTOByName(String name) {
		for (ServletContextDTO servletContextDTO : getServletContextDTOs()) {
			if (name.equals(servletContextDTO.name)) {
				return servletContextDTO;
			}
		}

		return null;
	}

	protected ServletContextDTO[] getServletContextDTOs() {
		return getHttpServiceRuntime().getRuntimeDTO().servletContextDTOs;
	}

	protected ErrorPageDTO getErrorPageDTOByName(String context, String name) {
		ServletContextDTO servletContextDTO = getServletContextDTOByName(context);

		if (servletContextDTO == null) {
			return null;
		}

		for (ErrorPageDTO errorPageDTO : servletContextDTO.errorPageDTOs) {
			if (name.equals(errorPageDTO.name)) {
				return errorPageDTO;
			}
		}

		return null;
	}

	protected FailedErrorPageDTO getFailedErrorPageDTOByName(String name) {
		for (FailedErrorPageDTO failedErrorPageDTO : getFailedErrorPageDTOs()) {
			if (name.equals(failedErrorPageDTO.name)) {
				return failedErrorPageDTO;
			}
		}

		return null;
	}

	protected FailedErrorPageDTO[] getFailedErrorPageDTOs() {
		HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime();

		return httpServiceRuntime.getRuntimeDTO().failedErrorPageDTOs;
	}

	protected FilterDTO getFilterDTOByName(String contextName, String name) {
		ServletContextDTO servletContextDTO = getServletContextDTOByName(contextName);

		if (servletContextDTO == null) {
			return null;
		}

		for (FilterDTO filterDTO : servletContextDTO.filterDTOs) {
			if (name.equals(filterDTO.name)) {
				return filterDTO;
			}
		}

		return null;
	}

	protected FailedFilterDTO getFailedFilterDTOByName(String name) {
		for (FailedFilterDTO failedFilterDTO : getFailedFilterDTOs()) {
			if (name.equals(failedFilterDTO.name)) {
				return failedFilterDTO;
			}
		}

		return null;
	}

	protected FailedFilterDTO[] getFailedFilterDTOs() {
		return getHttpServiceRuntime().getRuntimeDTO().failedFilterDTOs;
	}

	protected FailedServletContextDTO getFailedServletContextDTOByName(String name) {
		for (FailedServletContextDTO failedServletContextDTO : getFailedServletContextDTOs()) {
			if (name.equals(failedServletContextDTO.name)) {
				return failedServletContextDTO;
			}
		}

		return null;
	}

	protected FailedServletContextDTO[] getFailedServletContextDTOs() {
		return getHttpServiceRuntime().getRuntimeDTO().failedServletContextDTOs;
	}

	protected ResourceDTO getResourceDTOByServiceId(String contextName, long serviceId) {
		ServletContextDTO servletContextDTO = getServletContextDTOByName(contextName);

		if (servletContextDTO == null) {
			return null;
		}

		for (ResourceDTO resourceDTO : servletContextDTO.resourceDTOs) {
			if (serviceId == resourceDTO.serviceId) {
				return resourceDTO;
			}
		}

		return null;
	}

	protected FailedResourceDTO getFailedResourceDTOByServiceId(long serviceId) {
		for (FailedResourceDTO failedResourceDTO : getFailedResourceDTOs()) {
			if (serviceId == failedResourceDTO.serviceId) {
				return failedResourceDTO;
			}
		}

		return null;
	}

	protected FailedResourceDTO[] getFailedResourceDTOs() {
		return getHttpServiceRuntime().getRuntimeDTO().failedResourceDTOs;
	}

	protected static final String PROTOTYPE = "prototype/";
	protected static final String CONFIGURE = "configure";
	protected static final String UNREGISTER = "unregister";
	protected static final String ERROR = "error";
	protected static final String STATUS_PARAM = "servlet.init.status";
	protected static final String TEST_PROTOTYPE_NAME = "test.prototype.name";
	protected static final String TEST_PATH_CUSTOMIZER_NAME = "test.path.customizer.name";
	protected static final String TEST_ERROR_CODE = "test.error.code";

	protected static final String EQUINOX_DS_BUNDLE = "org.apache.felix.scr";
	protected static final String EQUINOX_JETTY_BUNDLE = "org.eclipse.equinox.http.jetty";
	protected static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty.";
	protected static final String OSGI_HTTP_PORT_PROPERTY = "org.osgi.service.http.port";
	protected static final String STATUS_OK = "OK";
	protected static final String TEST_BUNDLES_BINARY_DIRECTORY = "/bundles_bin/";
	protected static final String TEST_BUNDLE_1 = "tb1";
	protected static final String TEST_BUNDLE_2 = "tb2";

	protected static final String[] BUNDLES = new String[] {
		EQUINOX_DS_BUNDLE
	};

	protected BundleInstaller installer;
	protected BundleAdvisor advisor;
	protected ServletRequestAdvisor requestAdvisor;
	protected final Collection<ServiceRegistration<? extends Object>> registrations = new ArrayList<ServiceRegistration<? extends Object>>();
	protected ServiceTracker<HttpServiceRuntime, HttpServiceRuntime> runtimeTracker;

	protected static class TestFilter implements Filter {
		AtomicInteger called = new AtomicInteger(0);

		public TestFilter() {}

		@Override
		public void init(FilterConfig filterConfig) throws ServletException {
			// nothing
		}

		@Override
		public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
				throws IOException, ServletException {
			called.incrementAndGet();
			chain.doFilter(request, response);
		}

		@Override
		public void destroy() {
			// nothing
		}

		public void clear() {
			called.set(0);
		}

		public boolean getCalled() {
			return called.get() >= 1;
		}

		public int getCount() {
			return called.get();
		}
	}

	protected static class TestServletContextHelperFactory implements ServiceFactory<ServletContextHelper> {
		static class TestServletContextHelper extends ServletContextHelper {
			public TestServletContextHelper(Bundle bundle) {
				super(bundle);
			}};

		public TestServletContextHelperFactory() {}

		@Override
		public ServletContextHelper getService(Bundle bundle, ServiceRegistration<ServletContextHelper> registration) {
			return new TestServletContextHelper(bundle);
		}

		@Override
		public void ungetService(Bundle bundle, ServiceRegistration<ServletContextHelper> registration,
				ServletContextHelper service) {
			// nothing
		}

	}

	protected static class TestContextPathAdaptor extends ContextPathCustomizer {
		private final String defaultFilter;
		private final String contextPrefix;
		private final String testName;

		/**
		 * @param defaultFilter
		 * @param contextPrefix
		 */
		public TestContextPathAdaptor(String defaultFilter, String contextPrefix, String testName) {
			super();
			this.defaultFilter = defaultFilter;
			this.contextPrefix = contextPrefix;
			this.testName = testName;
		}

		@Override
		public String getDefaultContextSelectFilter(ServiceReference<?> httpWhiteBoardService) {
			if (testName.equals(httpWhiteBoardService.getProperty("servlet.init." + TEST_PATH_CUSTOMIZER_NAME))) {
				return defaultFilter;
			}
			return null;
		}

		@Override
		public String getContextPathPrefix(ServiceReference<ServletContextHelper> helper) {
			if (testName.equals(helper.getProperty(TEST_PATH_CUSTOMIZER_NAME))) {
				return contextPrefix;
			}
			return null;
		}

	}

	protected static class ErrorServlet extends HttpServlet{
		private static final long serialVersionUID = 1L;
		private final String errorCode;

		public ErrorServlet(String errorCode) {
			super();
			this.errorCode = errorCode;
		}

		@Override
		protected void service(
				HttpServletRequest request, HttpServletResponse response)
			throws ServletException ,IOException {

			if (response.isCommitted()) {
				System.out.println("Problem?");

				return;
			}

			PrintWriter writer = response.getWriter();

			String requestURI = (String)request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
			Integer status = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);

			writer.print(errorCode + " : " + status + " : ERROR : " + requestURI);
		}

	};

}
