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

namespace edu.neu.ccs.demeterf.http.classes{

using edu.neu.ccs.demeterf.lib;
using System.Net.Sockets;
using System.Text;
using System.IO;

using System;



/** Representation of HTTPResp */
public class HTTPResp{
    protected readonly HTTPVer ver;
    protected readonly int resp;
    protected readonly ident label;
    protected readonly List<MsgHead> keys;
    protected readonly 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 override bool Equals(Object o){
        if(!(o is HTTPResp))return false;
        if(o == this)return true;
        HTTPResp oo = (HTTPResp)o;
        return (ver.Equals(oo.ver))&&(resp.Equals(oo.resp))&&(label.Equals(oo.label))&&(keys.Equals(oo.keys))&&(body.Equals(oo.body));
    }

    /** Field Class for HTTPResp.ver */
    public class verF : edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.resp */
    public class respF : edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.label */
    public class labelF : edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.keys */
    public class keysF : edu.neu.ccs.demeterf.Fields.any{}
    /** Field Class for HTTPResp.body */
    public class bodyF : edu.neu.ccs.demeterf.Fields.any{}

    /** Basic Response Numbers */
    public static readonly 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 readonly 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",""+DateTime.Now),
                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 htmlError(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 bool isOK(){ return resp >= MIN_OK && resp <= MAX_OK; }
    /** Is this Response an Error? */
    public bool isError(){ return resp >= MIN_ERROR && resp <= MAX_ERROR; }
    /** Is this Response a Server Error? */
    public bool isServerError(){ return resp >= MIN_SERVER_ERROR && resp <= MAX_ERROR; }
    /** Is this Response a Client Error? */
    public bool isClientError(){ return resp >= MIN_ERROR && resp < MIN_SERVER_ERROR; }
    
    /** Write a Response to a Socket */
    public void toSocket(Socket s){
        try{
            StreamWriter outt = new StreamWriter(new NetworkStream(s));
            outt.Write(this.ToString());
            outt.Flush();
            s.Shutdown(SocketShutdown.Send);
        }catch(Exception e){ throw 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, int respTimeout){
        try{
            //s.ReceiveTimeout = HTTPReq.DEFAULT_RESP_TIMEOUT;
            s.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveTimeout, HTTPReq.DEFAULT_RESP_TIMEOUT);
            HTTPResp resp = fromInputStream(new NetworkStream(s), respTimeout);
            s.Shutdown(SocketShutdown.Receive);
            return resp;
        }catch(Exception e){ throw e; }
    }
    /** Read a Response from an Input Stream */
    public static HTTPResp fromInputStream(Stream inpt, long timeout){
        try{
            StreamReader inn = new StreamReader(inpt);
            String first = HTTPReq.readLine(inn,timeout);
             if(first == null)throw new Exception("Empty HTTP Header");
            HTTPVer v = HTTPVer.Parse(first);
            first = first.Substring(first.IndexOf(' ')+1);
            int b = first.IndexOf(' '),
                rnum = Int32.Parse(first.Substring(0,b));
            return new HTTPResp(v, rnum, new ident(first.Substring(b+1)),
                                HTTPReq.ParseMsgHeads(inn,timeout),
                                HTTPReq.ParseBody(inn,timeout));
        }catch(Exception e){ throw 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 PrintToString */
    public override String ToString(){ return global::edu.neu.ccs.demeterf.http.classes.PrintToString.PrintToStringM(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; }

}
}