package org.apache.commons.jcs3.auxiliary.remote.http.server;

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

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.jcs3.access.exception.CacheException;
import org.apache.commons.jcs3.auxiliary.AuxiliaryCacheConfigurator;
import org.apache.commons.jcs3.auxiliary.remote.http.behavior.IRemoteHttpCacheConstants;
import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheRequest;
import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheResponse;
import org.apache.commons.jcs3.engine.behavior.ICacheElement;
import org.apache.commons.jcs3.engine.behavior.ICacheServiceNonLocal;
import org.apache.commons.jcs3.engine.behavior.ICompositeCacheManager;
import org.apache.commons.jcs3.engine.control.CompositeCacheManager;
import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger;
import org.apache.commons.jcs3.io.ObjectInputStreamClassLoaderAware;
import org.apache.commons.jcs3.log.Log;
import org.apache.commons.jcs3.log.LogManager;
import org.apache.commons.jcs3.utils.config.PropertySetter;
import org.apache.commons.jcs3.utils.serialization.StandardSerializer;

/**
 * This servlet simply reads and writes objects. The requests are packaged in a general wrapper. The
 * processor works on the wrapper object and returns a response wrapper.
 */
public class RemoteHttpCacheServlet
    extends HttpServlet
{
    /** Don't change. */
    private static final long serialVersionUID = 8752849397531933346L;

    /** The Logger. */
    private static final Log log = LogManager.getLog( RemoteHttpCacheServlet.class );

    /** The cache manager */
    private static CompositeCacheManager cacheMgr;

    /** The service that does the work. */
    private static ICacheServiceNonLocal<Serializable, Serializable> remoteCacheService;

    /** This needs to be standard, since the other side is standard */
    private final StandardSerializer serializer = new StandardSerializer();

    /** Number of service calls. */
    private int serviceCalls = 0;

    /** The interval at which we will log the count. */
    private final int logInterval = 100;

    /**
     * Initializes the cache.
     * <p>
     * This provides an easy extension point. Simply extend this servlet and override the init
     * method to change the way the properties are loaded.
     * @param config
     * @throws ServletException
     */
    @Override
    public void init( ServletConfig config )
        throws ServletException
    {
        try
        {
            cacheMgr = CompositeCacheManager.getInstance();
        }
        catch (CacheException e)
        {
            throw new ServletException(e);
        }

        remoteCacheService = createRemoteHttpCacheService( cacheMgr );

        super.init( config );
    }

    /**
     * Read the request, call the processor, write the response.
     * <p>
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service( HttpServletRequest request, HttpServletResponse response )
        throws ServletException, IOException
    {
        incrementServiceCallCount();
        log.debug( "Servicing a request. {0}", request );

        RemoteCacheRequest<Serializable, Serializable> remoteRequest = readRequest( request );
        RemoteCacheResponse<Object> cacheResponse = processRequest( remoteRequest );

        writeResponse( response, cacheResponse );
    }

    /**
     * Read the request from the input stream.
     * <p>
     * @param request
     * @return RemoteHttpCacheRequest
     */
    protected RemoteCacheRequest<Serializable, Serializable> readRequest( HttpServletRequest request )
    {
        RemoteCacheRequest<Serializable, Serializable> remoteRequest = null;
        try
        {
            InputStream inputStream = request.getInputStream();
            log.debug( "After getting input stream and before reading it" );

            remoteRequest = readRequestFromStream( inputStream );
        }
        catch ( Exception e )
        {
            log.error( "Could not get a RemoteHttpCacheRequest object from the input stream.", e );
        }
        return remoteRequest;
    }

    /**
     * Reads the response from the stream and then closes it.
     * <p>
     * @param inputStream
     * @return RemoteHttpCacheRequest
     * @throws IOException
     * @throws ClassNotFoundException
     */
    protected RemoteCacheRequest<Serializable, Serializable> readRequestFromStream( InputStream inputStream )
        throws IOException, ClassNotFoundException
    {
        ObjectInputStream ois = new ObjectInputStreamClassLoaderAware( inputStream, null );

        @SuppressWarnings("unchecked") // Need to cast from Object
        RemoteCacheRequest<Serializable, Serializable> remoteRequest
            = (RemoteCacheRequest<Serializable, Serializable>) ois.readObject();
        ois.close();
        return remoteRequest;
    }

    /**
     * Write the response to the output stream.
     * <p>
     * @param response
     * @param cacheResponse
     */
    protected void writeResponse( HttpServletResponse response, RemoteCacheResponse<Object> cacheResponse )
    {
        try
        {
            response.setContentType( "application/octet-stream" );

            byte[] responseAsByteAray = serializer.serialize( cacheResponse );
            response.setContentLength( responseAsByteAray.length );

            OutputStream outputStream = response.getOutputStream();
            log.debug( "Opened output stream.  Response size: {0}",
                    () -> responseAsByteAray.length );
            // WRITE
            outputStream.write( responseAsByteAray );
            outputStream.flush();
            outputStream.close();
        }
        catch ( IOException e )
        {
            log.error( "Problem writing response. {0}", cacheResponse, e );
        }
    }

    /**
     * Processes the request. It will call the appropriate method on the service
     * <p>
     * @param request
     * @return RemoteHttpCacheResponse, never null
     */
    protected RemoteCacheResponse<Object> processRequest( RemoteCacheRequest<Serializable, Serializable> request )
    {
        RemoteCacheResponse<Object> response = new RemoteCacheResponse<>();

        if ( request == null )
        {
            String message = "The request is null. Cannot process";
            log.warn( message );
            response.setSuccess( false );
            response.setErrorMessage( message );
        }
        else
        {
            try
            {
                switch ( request.getRequestType() )
                {
                    case GET:
                        ICacheElement<Serializable, Serializable> element =
                            remoteCacheService.get( request.getCacheName(), request.getKey(), request.getRequesterId() );
                        response.setPayload(element);
                        break;
                    case GET_MULTIPLE:
                        Map<Serializable, ICacheElement<Serializable, Serializable>> elementMap =
                            remoteCacheService.getMultiple( request.getCacheName(), request.getKeySet(), request.getRequesterId() );
                        if ( elementMap != null )
                        {
                            response.setPayload(new HashMap<>(elementMap));
                        }
                        break;
                    case GET_MATCHING:
                        Map<Serializable, ICacheElement<Serializable, Serializable>> elementMapMatching =
                            remoteCacheService.getMatching( request.getCacheName(), request.getPattern(), request.getRequesterId() );
                        if ( elementMapMatching != null )
                        {
                            response.setPayload(new HashMap<>(elementMapMatching));
                        }
                        break;
                    case REMOVE:
                        remoteCacheService.remove( request.getCacheName(), request.getKey(), request.getRequesterId() );
                        break;
                    case REMOVE_ALL:
                        remoteCacheService.removeAll( request.getCacheName(), request.getRequesterId() );
                        break;
                    case UPDATE:
                        remoteCacheService.update( request.getCacheElement(), request.getRequesterId() );
                        break;
                    case ALIVE_CHECK:
                    case DISPOSE:
                        response.setSuccess( true );
                        // DO NOTHING
                        break;
                    case GET_KEYSET:
                        Set<Serializable> keys = remoteCacheService.getKeySet( request.getCacheName() );
                        response.setPayload( keys );
                        break;
                    default:
                        String message = "Unknown event type.  Cannot process " + request;
                        log.warn( message );
                        response.setSuccess( false );
                        response.setErrorMessage( message );
                        break;
                }
            }
            catch ( IOException e )
            {
                String message = "Problem processing request. " + request + " Error: " + e.getMessage();
                log.error( message, e );
                response.setSuccess( false );
                response.setErrorMessage( message );
            }
        }

        return response;
    }

    /**
     * Configures the attributes and the event logger and constructs a service.
     * <p>
     * @param cacheManager
     * @return RemoteHttpCacheService
     */
    protected <K, V> RemoteHttpCacheService<K, V> createRemoteHttpCacheService( ICompositeCacheManager cacheManager )
    {
        Properties props = cacheManager.getConfigurationProperties();
        ICacheEventLogger cacheEventLogger = configureCacheEventLogger( props );
        RemoteHttpCacheServerAttributes attributes = configureRemoteHttpCacheServerAttributes( props );

        RemoteHttpCacheService<K, V> service = new RemoteHttpCacheService<>( cacheManager, attributes, cacheEventLogger );
        log.info( "Created new RemoteHttpCacheService {0}", service );
        return service;
    }

    /**
     * Tries to get the event logger.
     * <p>
     * @param props
     * @return ICacheEventLogger
     */
    protected ICacheEventLogger configureCacheEventLogger( Properties props )
    {
        ICacheEventLogger cacheEventLogger = AuxiliaryCacheConfigurator
            .parseCacheEventLogger( props, IRemoteHttpCacheConstants.HTTP_CACHE_SERVER_PREFIX );

        return cacheEventLogger;
    }

    /**
     * Configure.
     * <p>
     * jcs.remotehttpcache.serverattributes.ATTRIBUTENAME=ATTRIBUTEVALUE
     * <p>
     * @param prop
     * @return RemoteCacheServerAttributesconfigureRemoteCacheServerAttributes
     */
    protected RemoteHttpCacheServerAttributes configureRemoteHttpCacheServerAttributes( Properties prop )
    {
        RemoteHttpCacheServerAttributes rcsa = new RemoteHttpCacheServerAttributes();

        // configure automatically
        PropertySetter.setProperties( rcsa, prop,
                                      IRemoteHttpCacheConstants.HTTP_CACHE_SERVER_ATTRIBUTES_PROPERTY_PREFIX + "." );

        return rcsa;
    }

    /**
     * @param rcs the remoteCacheService to set
     */
    protected void setRemoteCacheService(ICacheServiceNonLocal<Serializable, Serializable> rcs)
    {
        remoteCacheService = rcs;
    }

    /**
     * Log some details.
     */
    private void incrementServiceCallCount()
    {
        // not thread safe, but it doesn't have to be accurate
        serviceCalls++;
        if ( log.isInfoEnabled() )
        {
            if ( serviceCalls % logInterval == 0 )
            {
                log.info( "serviceCalls = {0}", serviceCalls );
            }
        }
    }

    /** Release the cache manager. */
    @Override
    public void destroy()
    {
        log.info( "Servlet Destroyed, shutting down JCS." );

        cacheMgr.shutDown();
    }

    /**
     * Get servlet information
     * <p>
     * @return basic info
     */
    @Override
    public String getServletInfo()
    {
        return "RemoteHttpCacheServlet";
    }
}
