package org.wikiwebserver.handler.http;

import java.io.ByteArrayOutputStream;

import org.wikiwebserver.core.ConfigManager;

public class HTTPResponse {
    
    private static final String LF = "\r\n";    
    private static final int MAX_OUTPUT_CACHE_SIZE =
    	ConfigManager.getInt("http.max-cacheable-response-size"); 
    
    private int code;
    private String info;
    private int versionMajor = 1, versionMinor = 0;
    private HTTPHeaders headers;
    
    private Object data;    
    private Throwable exception;      
    
    private String cacheKey;
    private long cacheExpireTime;
    private ByteArrayOutputStream cacheStream;
    
    private long numBytesWritten = 0;
  
    private long finishTime;
    
    public int getVersionMajor() {
        return this.versionMajor;
    }
    
    void setVersionMajor(int versionMajor) {
        this.versionMajor = versionMajor;
    }
    
    public int getVersionMinor() {
        return this.versionMinor;
    }
    
    void setVersionMinor(int versionMinor) {
        this.versionMinor = versionMinor;
    }   
    
    public int getCode() {
        return this.code;
    }
    
    public void setCode(int code) {
        this.code = code;
    }
    
    public String getInfo() {
        return this.info;
    }
    
    public void setInfo(String info) {
        this.info = info;
    }
    
    public HTTPHeaders getHeaders() {
        return this.headers;
    }
    
    public void setHeaders(HTTPHeaders headers) {
        this.headers = headers;
    }
    
    public Object getData() {
        return data;
    }
    
    public void setData(Object data) {
        this.data = data;
    }
    
    public Throwable getException() {
        return exception;
    }
    
    public void setException(Throwable t) {
        this.exception = t;
    }    
    
    public void setCacheKey(String cacheKey) {
        this.cacheKey = cacheKey;        
        if (cacheKey != null && this.numBytesWritten < MAX_OUTPUT_CACHE_SIZE) {
            if (cacheStream == null) {
                cacheStream = new ByteArrayOutputStream(1024);
            }
        }
        else cacheStream = null;
    }
    
    public String getCacheKey() {
        return this.cacheKey;
    }
    
    public long getCacheExpireTime() {
        return this.cacheExpireTime;
    }
    
    public void setCacheExpireTime(long time) {
        this.cacheExpireTime = time;
    }
    
    public boolean isCacheable() {
        return (cacheKey != null && cacheStream != null);
    }
    
    public ByteArrayOutputStream getCacheStream() {
        return cacheStream;
    }
    
    public long getNumBytesWritten() {
        return this.numBytesWritten;
    }
    
    public long getFinishTime() {
		return this.finishTime;
	}

	void setFinishTime(long finishTime) {
		this.finishTime = finishTime;
	}

	void incrementNumBytesWritten(int amount) {
        this.numBytesWritten += amount;
        // Too many bytes written, stop caching output
        if (this.numBytesWritten > MAX_OUTPUT_CACHE_SIZE) {
            setCacheKey(null);
        }
    }
    
    public String toString() {
        StringBuilder buffer = new StringBuilder(1024);
        buffer.append("HTTP/");
        buffer.append(String.valueOf(versionMajor));
        buffer.append(".");
        buffer.append(String.valueOf(versionMinor));
        buffer.append(" ");
        buffer.append(getCode());
        buffer.append(" ");
        buffer.append(getInfo());
        buffer.append(LF);
        
        // Some status codes must not include the content length header
        int code = getCode();
        if (code == 100 || code == 101 || code == 102 || code == 204 || code == 304) {
            getHeaders().remove("Content-Length");
        }
        
        buffer.append(headers.toString());
        buffer.append(LF);
       
        return buffer.toString();
    }    
}

