/*
 * 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.tuscany.sca.binding.rest.provider;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.MessageBodyWriter;

import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.binding.rest.RESTBinding;
import org.apache.tuscany.sca.common.http.HTTPCacheContext;
import org.apache.tuscany.sca.common.http.HTTPContext;
import org.apache.tuscany.sca.common.http.HTTPHeader;
import org.apache.tuscany.sca.common.http.ThreadHTTPContext;
import org.apache.tuscany.sca.common.http.cors.CORSHeaderProcessor;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.extensibility.ClassLoaderContext;
import org.apache.wink.common.internal.registry.ProvidersRegistry;
import org.apache.wink.common.model.wadl.WADLGenerator;
import org.apache.wink.server.handlers.HandlersChain;
import org.apache.wink.server.handlers.MessageContext;
import org.apache.wink.server.handlers.ResponseHandler;
import org.apache.wink.server.internal.DeploymentConfiguration;
import org.apache.wink.server.internal.servlet.RestServlet;

/**
 *
 */
public class TuscanyRESTServlet extends RestServlet {
    private static final long serialVersionUID = 89997233133964915L;
    
    private static final Logger logger = Logger.getLogger(TuscanyRESTServlet.class.getName());
    
    private static final Annotation[] annotations = new Annotation[0];

    
    private ExtensionPointRegistry registry;
    private RESTBinding binding;
    private Class<?> resourceClass;

    public TuscanyRESTServlet(ExtensionPointRegistry registry, Binding binding, Class<?> resourceClass) {
        super();
        this.registry = registry;
        this.binding = (RESTBinding) binding;
        this.resourceClass = resourceClass;
    }

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        if (binding.isCORS()) {
            CORSHeaderProcessor.processCORS(binding.getCORSConfiguration(), request, response);
        }

        //create context
        HTTPContext bindingContext = new HTTPContext();
        bindingContext.setHttpRequest(request);
        bindingContext.setHttpResponse(response);
        

        try {
            //store in thread local
            ThreadHTTPContext.setHTTPContext(bindingContext);
            ThreadBindingContext.setBindingContext(binding);
            
            // handle special ?wadl request
            String query = request.getQueryString();
            if(query != null && query.indexOf("wadl") >= 0) {
                handleWadlRequest(request, response);
            } else {
                super.service(request, response);
            }
        } finally {
            //remove
            ThreadHTTPContext.removeHTTPContext();
            ThreadBindingContext.removeBindingContext();
        }
    }


    public void init() throws ServletException {
        ClassLoader cl =
            ClassLoaderContext.setContextClassLoader(Thread.currentThread().getContextClassLoader(),
                                                     registry.getServiceDiscovery(),
                                                     "/META-INF/server/wink-providers",
                                                     "javax.ws.rs.ext.RuntimeDelegate");
        try {
            super.init();
        } finally {
            if (cl != null) {
                // return previous classLoader
                Thread.currentThread().setContextClassLoader(cl);
            }
        }
    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    @Override
    public DeploymentConfiguration getDeploymentConfiguration() throws ClassNotFoundException, InstantiationException,
        IllegalAccessException, IOException {

        DeploymentConfiguration config =
            (DeploymentConfiguration)getServletContext().getAttribute(DeploymentConfiguration.class.getName());
        if (config != null) {
            return config;
        }

        // setup proper classLoader to work on OSGi environment
        ClassLoader cl =
            ClassLoaderContext.setContextClassLoader(Thread.currentThread().getContextClassLoader(),
                                                     registry.getServiceDiscovery(),
                                                     "javax.ws.rs.ext.RuntimeDelegate",
                                                     "/META-INF/wink-alternate-shortcuts.properties",
                                                     "/META-INF/server/wink-providers");

        try {
            config = super.getDeploymentConfiguration();
            getServletContext().setAttribute(DeploymentConfiguration.class.getName(), config);
        } finally {
            if (cl != null) {
                // return previous classLoader
                Thread.currentThread().setContextClassLoader(cl);
            }
        }

        // [rfeng] FIXME: This is a hack to fool Apache wink to not remove the servlet path
        config.setFilterConfig(new FilterConfig() {

            public ServletContext getServletContext() {
                return TuscanyRESTServlet.this.getServletContext();
            }

            public Enumeration getInitParameterNames() {
                return TuscanyRESTServlet.this.getInitParameterNames();
            }

            public String getInitParameter(String p) {
                return TuscanyRESTServlet.this.getInitParameter(p);
            }

            public String getFilterName() {
                return TuscanyRESTServlet.this.getServletName();
            }
        });
        
        Properties properties = new Properties();
        properties.put("wink.context.uri", getBindingContext());
        //properties.put("wink.http.uri", binding.getURI());

        config.setProperties(properties);

        ProvidersRegistry providers = config.getProvidersRegistry();
        providers.addProvider(new DataBindingJAXRSReader(registry), 0.2, true);
        providers.addProvider(new DataBindingJAXRSWriter(registry), 0.2, true);

        config.getResponseUserHandlers().add(new TuscanyResponseHandler());

        return config;
    }
    
    private void handleWadlRequest(HttpServletRequest request, HttpServletResponse response) {
        try {
            org.apache.wink.common.model.wadl.Application wadlDocument = null;
            WADLGenerator generator = new WADLGenerator();
            Set<Class<?>> classes = new HashSet<Class<?>>();
            classes.add(resourceClass);
            wadlDocument = generator.generate(binding.getURI(), classes);
            
            MessageBodyWriter<org.apache.wink.common.model.wadl.Application> writer = 
                this.getDeploymentConfiguration().getProvidersRegistry().
                     getMessageBodyWriter(org.apache.wink.common.model.wadl.Application.class, 
                                          org.apache.wink.common.model.wadl.Application.class,
                                          annotations, 
                                          MediaType.APPLICATION_XML_TYPE,
                                          null);
            
            writer.writeTo(wadlDocument, 
                           org.apache.wink.common.model.wadl.Application.class, 
                           org.apache.wink.common.model.wadl.Application.class, 
                           annotations,
                           MediaType.APPLICATION_XML_TYPE,
                           null, response.getOutputStream());
            
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }
    
    private String getBindingContext() {
        Pattern pattern = Pattern.compile("^[^#]*?://.*?(/.*)$");
        Matcher matcher = pattern.matcher(binding.getURI());
        if(matcher.find()) {
            String bindingContext = matcher.group(1);
            return bindingContext;
        }
        return null;
    }

    /**
     * TuscanyResponseHandler
     * 
     * The response handler is shared, that's why we need to get the 
     * binding from the thread context otherwise different components
     * might get wrong binding configuration (e.g. headers)
     *
     * Required to support declarative HTTP Headers
     */
    class TuscanyResponseHandler implements ResponseHandler {
        public void handleResponse(MessageContext context, HandlersChain chain) throws Throwable {

            // assert response is not committed
            final HttpServletResponse httpResponse = context.getAttribute(HttpServletResponse.class);
            if (httpResponse.isCommitted()) {
                logger.log(Level.FINE, "The response is already committed. Nothing to do.");
                return;
            }

            RESTBinding binding = ThreadBindingContext.getBindingContext(); 
                
            //process declarative headers
            for(HTTPHeader header : binding.getHttpHeaders()) {
                //treat special headers that need to be calculated
                if(header.getName().equalsIgnoreCase("Expires")) {
                    GregorianCalendar calendar = new GregorianCalendar();
                    calendar.setTime(new Date());

                    calendar.add(Calendar.HOUR, Integer.parseInt(header.getValue()));

                    httpResponse.setHeader("Expires", HTTPCacheContext.RFC822DateFormat.format( calendar.getTime() ));
                } else {
                    //default behaviour to pass the header value to HTTP response
                    httpResponse.setHeader(header.getName(), header.getValue());
                }
            }

            chain.doChain(context);
        }

        public void init(Properties props) {

        }
    }
}
