# -*- coding: UTF-8 -*-
#    This file is part of arena.
#   
#    arena is free software: you can redistribute it and/or modify it
#    under the terms of the GNU General Public License as published by the
#    Free Software Foundation; either version 3 of the License or, at your
#    option, any later version.
#
#    arena is distributed in the hope that it will be useful, but
#    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABLITY
#    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
#    License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with arena.  If not, see <http://www.gnu.org/licenses/>. 

## @file
#  This file defines a class that consolidates the various variables related to
#  an HTTP request.

from Library.Base.Classwork import AnObject
from Library.String.PyStrings import IsPrintable

from Library.IO.HTTP.RequestInfo import HTTPRequestContentInfo, \
  HTTPRequestDateInfo, HTTPRequestDocumentInfo, HTTPRequestPathInfo, \
  HTTPRequestRemoteInfo, HTTPRequestRequestInfo, HTTPRequestScriptInfo, \
  HTTPRequestServerInfo, HTTPRequestHTTPInfo
  
import os, time, urlparse, Cookie

## The error message used when an attempt is made to retrieve a non-existent
#  item from an HTTP request
hrErrorRetrievingItem = ("Failed to retrieve the item \"{itemname}\""
                         " from {classname}")

## This class consolidates the various variables related to an HTTP 
#  request.  It can retrieve these from the environment and can print them to
#  a stream.
class AnHTTPRequest(AnObject, IsPrintable):
        
    ## Constructor
    def __init__(Self):
        AnObject.__init__(Self)
        
    ## Initializer        
    def init(Self):
        
        result = AnObject.init(Self)
        
        if result == True:
            Self.authType = ""
            Self.Content = HTTPRequestContentInfo()
            Self.Date = HTTPRequestDateInfo()
            Self.Document = HTTPRequestDocumentInfo()
            Self.gatewayInterface = ""           
            Self.Path = HTTPRequestPathInfo()
            Self.queryString = ""
            Self.query = {}
            Self.Remote = HTTPRequestRemoteInfo()
            Self.Request = HTTPRequestRequestInfo()
            Self.Script = HTTPRequestScriptInfo()
            Self.Server = HTTPRequestServerInfo()
            Self.HTTP = HTTPRequestHTTPInfo()
            Self.Cookie = Cookie.SimpleCookie()            
            
        return result
    
    ## Destructor    
    def __del__(Self):
        del Self.Content
        del Self.Date
        del Self.Document
        del Self.Path
        del Self.Remote
        del Self.Request
        del Self.Script
        del Self.Server
        del Self.HTTP
        del Self.Cookie
        
    ## Gets the values of the HTTP request from the environment.
    #    
    #  This method assumes that the script is being run as part of a CGI
    #  application.  It queries the appropriate environment variables and
    #  stores the values within the class instance attributes.
    def get(Self):
        Self.authType = os.environ.get('AUTH_TYPE')
        Self.Content.get()
        Self.Document.get()
        Self.gatewayInterface = os.getenv('GATEWAY_INTERFACE', "")
        Self.Path.get()        
        Self.queryString = os.getenv('QUERY_STRING', "")
        # Break out the query string, if we have one
        if len(Self.queryString) > 0:
            Self.query.update(urlparse.parse_qs(Self.queryString))
            # This is necessary because some values parsed from the query 
            # string are returned as lists with a single item
            for key, value in Self.query.iteritems():
                if (isinstance(value, list)) or (isinstance(value, tuple)):
                    Self.query[key] = value[0]
                        
        Self.Remote.get() 
        Self.Request.get()
        Self.Script.get()   
        Self.Server.get()
        Self.HTTP.get() 
        # Break out any cookies sent by the client
        if len(Self.HTTP.cookie) > 0:
            Self.Cookie.load(Self.HTTP.cookie)
        
    # IsPrintable implementation -----------------------------------------------
    ## Construct a string representation of the HTTP request.  This
    #  representation will be suitable for inclusion in the HTTP headers sent
    #  to a web server.
    def toString(Self):
        # Request method and URI
        result = Self.Request.toString()
        # Content
        result = result + Self.Content.toString()
        # Date
        result = result + Self.Date.toString()
        # HTTP
        result = result + Self.HTTP.toString()
        
        return result                

    # Properties ---------------------------------------------------------------
    ## Returns the named attribute.
    #    
    #  This method is provided for convenience; it allows access to the 
    #  AnHTTPRequest.query attribute, which is filled using the keys and 
    #  values provided in AnHTTPRequest.queryString.
    #
    #  Note that this routine disallows retrieving non-existent keys from 
    #  the query attributes list.
    def __getitem__(Self, key):
        if key in Self.query:
          return Self.query[key]
          
        raise KeyError(hrErrorRetrievingItem.format(attrname=key,
          classname=Self.name()))
          
    ## Determine whether the named attribute exists.
    #    
    #  This method is provided for convenience; it allows access to the 
    #  AnHTTPRequest.query attribute, which is filled using the keys and 
    #  values provided in AnHTTPRequest.queryString. 
    def __contains__(Self, key):
        return key in Self.query
