/*
 * Copyright 2013 Rackspace
 *
 *    Licensed 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 com.rackspacecloud.blueflood.http;

import com.google.common.annotations.VisibleForTesting;
import com.rackspacecloud.blueflood.service.Configuration;
import com.rackspacecloud.blueflood.service.CoreConfig;
import com.rackspacecloud.blueflood.service.HttpConfig;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static io.netty.handler.codec.http.HttpHeaders.Names.*;
import static io.netty.handler.codec.http.HttpHeaders.Values.*;
import static io.netty.handler.codec.http.HttpHeaders.isKeepAlive;
import static io.netty.handler.codec.http.HttpHeaders.setContentLength;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

public class HttpResponder {

    private static final boolean CORS_ENABLED = Configuration.getInstance().getBooleanProperty(CoreConfig.CORS_ENABLED);
    private static final String CORS_ALLOWED_ORIGINS = Configuration.getInstance().getStringProperty(CoreConfig.CORS_ALLOWED_ORIGINS);

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

    private static HttpResponder INSTANCE = new HttpResponder();

    public static HttpResponder getInstance() { return INSTANCE; }

    private int httpConnIdleTimeout =
            Configuration.getInstance().getIntegerProperty(HttpConfig.HTTP_CONNECTION_READ_IDLE_TIME_SECONDS);

    @VisibleForTesting
    HttpResponder() {}

    @VisibleForTesting
    HttpResponder(int httpConnIdleTimeout) {
        this.httpConnIdleTimeout = httpConnIdleTimeout;
    }

    public void respond(ChannelHandlerContext ctx, FullHttpRequest req, HttpResponseStatus status) {
        respond(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, status));
    }

    public void respond(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {

        // set response headers
        if (CORS_ENABLED) {
            res.headers().add("Access-Control-Allow-Origin", CORS_ALLOWED_ORIGINS);
        }

        if (res.content() != null) {
            setContentLength(res, res.content().readableBytes());
        }

        boolean isKeepAlive = false;
        // if this config is set to non zero, it means we intend
        // to close this connection after x seconds. We need to
        // respond back with the right header to indicate this
        if ( httpConnIdleTimeout >0 ) {
            res.headers().add(CONNECTION, CLOSE);
            res.headers().add(KEEP_ALIVE, "timeout="+httpConnIdleTimeout);
        } else {
            isKeepAlive = isKeepAlive(req);
            if (isKeepAlive) {
                res.headers().add(CONNECTION, KEEP_ALIVE);
            }
        }

        // Send the response and close the connection if necessary.
        ctx.channel().write(res);
        if (req == null || !isKeepAlive) {
            log.debug("Closing channel. isKeepAlive:" + isKeepAlive + " on channel: " + ctx.channel().toString());
            ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    }
}
@@ -1724,16 +1724,85 @@
 RIGINS);
+%0A    private static final String KEEP_ALIVE_TIMEOUT_STR = %22timeout=%22;
 %0A%0A    pr
@@ -2924,23 +2924,119 @@
 e = 
-false;%0A
+isKeepAlive(req);%0A        if (isKeepAlive) %7B%0A            res.headers().add(CONNECTION, KEEP_ALIVE);%0A%0A  
         
 // i
@@ -3031,16 +3031,18 @@
         
+  
 // if th
@@ -3090,16 +3090,20 @@
  intend%0A
+    
         
@@ -3166,16 +3166,20 @@
         
+    
 // respo
@@ -3207,16 +3207,17 @@
 t header
+s
  to indi
@@ -3230,24 +3230,28 @@
 his%0A        
+    
 if ( httpCon
@@ -3264,16 +3264,17 @@
 imeout %3E
+ 
 0 ) %7B%0A  
@@ -3287,269 +3287,86 @@
     
-res.headers().add(CONNECTION, CLOSE);%0A            res.headers().add(KEEP_ALIVE, %22timeout=%22+httpConnIdleTimeout);%0A        %7D else %7B%0A            isKeepAlive = isKeepAlive(req);%0A            if (isKeepAlive) %7B%0A                res.headers().add(CONNECTION, KEEP_ALIVE
+    res.headers().add(KEEP_ALIVE, KEEP_ALIVE_TIMEOUT_STR + httpConnIdleTimeout
 );%0A 

send connection: keep-alive instead of close