// ** This class was generated with DemFGen (vers:11/09/2009)

package edu.neu.ccs.demeterf.http.classes;

import edu.neu.ccs.demeterf.lib.*;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.InputStream;




/** Representation of HTTPResp */
public class HTTPResp{
    protected final HTTPVer ver;
    protected final int resp;
    protected final ident label;
    protected final List<MsgHead> keys;
    protected final ident body;

    /** Construct a(n) HTTPResp Instance */
    public HTTPResp(HTTPVer ver, int resp, ident label, List<MsgHead> keys, ident body){
        this.ver = ver;
        this.resp = resp;
        this.label = label;
        this.keys = keys;
        this.body = body;
    }
    /** Is the given object Equal to this HTTPResp? */
    public boolean equals(Object o){
        if(!(o instanceof HTTPResp))return false;
        if(o == this)return true;
        HTTPResp oo = (HTTPResp)o;
        return (((Object)ver).equals(oo.ver))&&(((Object)resp).equals(oo.resp))&&(((Object)label).equals(oo.label))&&(((Object)keys).equals(oo.keys))&&(((Object)body).equals(oo.body));
    }

    /** Field Class for HTTPResp.ver */
    public static class ver extends edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.resp */
    public static class resp extends edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.label */
    public static class label extends edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.keys */
    public static class keys extends edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.body */
    public static class body extends edu.neu.ccs.demeterf.Fields.any{}

    /** Basic Response Numbers */
    public static final int OK = 200,
                            NOT_FOUND = 404,
                            MIN_OK = OK,
                            MAX_OK = 299,
                            MIN_ERROR = 400,
                            MIN_SERVER_ERROR = 500,
                            MAX_ERROR = 599;
    /** Typical HTTP Version */
    public static final HTTPVer VER = new HTTPVer(1.0);
    
    /** Create a response with the given number, description, headers, and body */
    public static HTTPResp create(int resp, String desc, List<MsgHead> hds, String body){
        return createNoLen(resp, new ident(desc), hds.append(new MsgHead("Content-Length",""+body.length())),
                           new ident(body));
    }
    
    /** Create a response without adding the Length */
    private static HTTPResp createNoLen(int resp, ident label, List<MsgHead> hds, ident body){
        return new HTTPResp(VER, resp, label, hds, body);
    }
    
    /** Create an OK Response with the given Content-Type/Body */
    public static HTTPResp ok(String type, String body){
        return create(OK, "OK", commonHeaders(type), body);
    }

	/** Common Headers: Date, Content-Type */
    private static List<MsgHead> commonHeaders(String type){
        return List.<MsgHead>create(
                new MsgHead("Date",""+new java.util.Date()),
                new MsgHead("Content-Type",type));
    }
    
    /** Create an (empty) Error Response */
    public static HTTPResp error(){ return textError(""); }
    /** Create an Error Response with t*/
    public static HTTPResp error(String body){ return textError(body); }
    /** Create an (empty) Error Response */
    public static HTTPResp error(int errCode, String msg, String body){
        return textError(errCode,msg,body);
    }
    
    /** Create an TEXT Error (File Not Found" Response with a Body */
    public static HTTPResp textError(String body){
        return textError(NOT_FOUND, "Not Found", body);
    }    
    /** Create an Texr Error Response with the given Code, Message and Body */
    public static HTTPResp textError(int errCode, String msg, String body){
        return create(errCode, msg, commonHeaders("text/plain"), body);
    }    
    /** Create an HTML Error "File Not Found") Response with a Body */
    public static HTTPResp htmlError(String body){
        return htmlError(NOT_FOUND, "Not Found", body);
    }    
    /** Create an HTML Error Response with a Body */
    public static HTTPResp htmlError(int errCode, String msg, String body){
        return create(errCode, msg, commonHeaders("text/html"), body);
    }
    /** Create a Plain Text Response */
    public static HTTPResp textResponse(String text){ return ok("text/plain", text); }
    /** Create an HTML Response */
    public static HTTPResp htmlResponse(String text){ return ok("text/html", text); }

    /** Add a given Message Header to this Response */
    public HTTPResp addHeader(String key, String val){
          return createNoLen(resp,label,keys.append(new MsgHead(key,val)),body);
    }

    /** Is this Response OK? */
    public boolean isOK(){ return resp >= MIN_OK && resp <= MAX_OK; }
    /** Is this Response an Error? */
    public boolean isError(){ return resp >= MIN_ERROR && resp <= MAX_ERROR; }
    /** Is this Response a Server Error? */
    public boolean isServerError(){ return resp >= MIN_SERVER_ERROR && resp <= MAX_ERROR; }
    /** Is this Response a Client Error? */
    public boolean isClientError(){ return resp >= MIN_ERROR && resp < MIN_SERVER_ERROR; }
    
    /** Write a Response to a Socket */
    public void toSocket(Socket s){
        try{
             PrintWriter outt = new PrintWriter(s.getOutputStream());
             outt.print(this.toString());
             outt.flush();
             s.shutdownOutput();
        }catch(IOException e){ throw new RuntimeException(e); }
    }

    /** Read a Response from a Socket */
    public static HTTPResp fromSocket(Socket s){ return fromSocket(s,0); }
    /** Read a Response from a Socket */
    public static HTTPResp fromSocket(Socket s, long maxBytes){ return fromSocket(s,0,maxBytes); }
    /** Read a Response from a Socket */
    public static HTTPResp fromSocket(Socket s, int respTimeout, long maxBytes){
         try{
            s.setSoTimeout(respTimeout);
            HTTPResp resp = fromInputStream(s.getInputStream(), respTimeout, maxBytes);
            s.shutdownInput();
            return resp;
        }catch(IOException e){ throw new RuntimeException(e); }
    }
    /** Read a Response from an Input Stream */
    public static HTTPResp fromInputStream(InputStream inpt){
        return fromInputStream(inpt,0);
    }
    /** Read a Response from an Input Stream */
    public static HTTPResp fromInputStream(InputStream inpt, long maxBytes){
        return fromInputStream(inpt,0,maxBytes);
    }
    /** Read a Response from an Input Stream */
    public static HTTPResp fromInputStream(InputStream inpt, long timeout, long maxBytes){
        try{
             BufferedReader inn = new BufferedReader(new InputStreamReader(inpt));
             String first = HTTPReq.readLine(inn,timeout);
             if(first == null)throw new RuntimeException("Empty HTTP Header");
             HTTPVer v = HTTPVer.parse(first);
             first = first.substring(first.indexOf(' ')+1);
             int b = first.indexOf(' '),
                 rnum = Integer.parseInt(first.substring(0,b));
             HTTPReq.CountHds headers = HTTPReq.parseMsgHeads(inn,timeout,maxBytes,maxBytes-(first.length()+1));
             return new HTTPResp(v, rnum, new ident(first.substring(b+1)),
                                 headers.heads,
                                 HTTPReq.parseBody(inn,timeout,maxBytes,maxBytes-(first.length()+1+headers.size)));
        }catch(RuntimeException e){ throw e;
        }catch(Exception e){ throw new RuntimeException(e); }
    }
    /** Get the body of this Response */
    public String getBodyString(){ return ""+body; }
    /** Return the headers (key/value Map) of this Response */
    public Map<String,String> getHeaders(){ return HTTPReq.getHeaders(keys); }

    /** DGP method from Class PrintHeapToString */
    public String toString(){ return edu.neu.ccs.demeterf.http.classes.PrintHeapToString.PrintHeapToStringM(this); }
    /** Getter for field HTTPResp.body */
    public ident getBody(){ return body; }
    /** Getter for field HTTPResp.keys */
    public List<MsgHead> getKeys(){ return keys; }
    /** Getter for field HTTPResp.label */
    public ident getLabel(){ return label; }
    /** Getter for field HTTPResp.resp */
    public int getResp(){ return resp; }
    /** Getter for field HTTPResp.ver */
    public HTTPVer getVer(){ return ver; }

}