/*
**
**      Copyright (c) 2000-2004 ChoiceStream, Inc.  All Rights Reserved
**
**      ChoiceStream
**      210 Broadway
**      Cambridge, MA 02139
**
**  $Id: curlhandle.h,v 1.20 2005/05/21 00:28:09 mmastroianni Exp $
**
**/
#ifndef CSM_MultiCurlHandle_H
#define CSM_MultiCurlHandle_H

typedef void CURL;
#include <vector>
#include <string>
#include <set>
#include "curl.h"

namespace csm
{

	enum HttpStatus // HTTP 1.1 (RFC 2616)
	{
		HTTP_NULL_STATUS = 0,
		HTTP_Continue = 100,
		HTTP_Switching_Protocols = 101,
		HTTP_OK = 200,
		HTTP_Created = 201,
		HTTP_Accepted = 202,
		HTTP_Non_Authoritative_Information = 203,
		HTTP_No_Content = 204,
		HTTP_Reset_Content = 205,
		HTTP_Partial_Content = 206,
		HTTP_Multiple_Choices = 300,
		HTTP_Moved_Permanently = 301,
		HTTP_Found = 302,
		HTTP_See_Other = 303,
		HTTP_Not_Modified = 304,
		HTTP_Use_Proxy = 305,
		HTTP_Temporary_Redirect = 307,
		HTTP_Bad_Request = 400,
		HTTP_Unauthorized = 401,
		HTTP_Payment_Required = 402,
		HTTP_Forbidden = 403,
		HTTP_Not_Found = 404,
		HTTP_Method_Not_Allowed = 405,
		HTTP_Not_Acceptable = 406,
		HTTP_Proxy_Authentication_Required = 407,
		HTTP_Request_Time_out = 408,
		HTTP_Conflict = 409,
		HTTP_Gone = 410,
		HTTP_Length_Required = 411,
		HTTP_Precondition_Failed = 412,
		HTTP_Request_Entity_Too_Large = 413,
		HTTP_Request_URI_Too_Large = 414,
		HTTP_Unsupported_Media_Type = 415,
		HTTP_Requested_range_not_satisfiable = 416,
		HTTP_Expectation_Failed = 417,
		HTTP_Internal_Server_Error = 500,
		HTTP_Not_Implemented = 501,
		HTTP_Bad_Gateway = 502,
		HTTP_Service_Unavailable = 503,
		HTTP_Gateway_Time_out = 504,
		HTTP_HTTP_Version_not_supported = 505,
	};
	typedef std::vector<std::string> HttpHeaders;
	struct HttpResponse
	{
		HttpResponse()
			: status(HTTP_NULL_STATUS)
		{
		}

		HttpHeaders headers;
		HttpStatus status;
		std::string body;
		std::string effectiveUrl;
		int redirectsFollowed;
	};


    struct CurlResponse : HttpResponse
    {
        CurlResponse(const std::string url):
            HttpResponse(),
            url_(url){};
        CURL * handle_;
        std::string url_;
        std::set<std::string> headerSet_;
    };

	typedef csm::CurlResponse * RefCurlResponse;
    typedef std::vector<RefCurlResponse> CurlResponseVec;

    class MultiCurlHandle
    {
      public: 
        MultiCurlHandle(bool useAltdns = false, const std::string & altdns1 = "", const std::string & altdns2 = "");
        ~MultiCurlHandle();

        bool getRequests(const std::vector<std::string> & urls, 
                         CurlResponseVec & results);
        //really experimental
        bool regetRequests(const std::vector<std::string> & urls, 
                           std::vector<RefCurlResponse> & results);
        void reInitHandle(int i, RefCurlResponse r);
        bool reInitHandles(const std::vector<std::string> & urls,
                           CurlResponseVec & results);
        //
        
        static void setDefaultCookieFile(const std::string & file){cookieFileDefault_ = file;};
        static void setDefaultUserAgent(const std::string & agent){userAgentDefault_ = agent;};
        static void setDefaultMaxFollow(int i){maxFollowDefault_ = i;};
        static void setDefaultTimeout(int i){timeoutDefault_ = i;};
        void setId(int id);             
        static bool acceptable(const std::string & contentType);
        
      protected:
        bool initHandle(RefCurlResponse r);
      private:
        void cleanup(CurlResponseVec & data);
        void addHandles(CURLM * multi, CurlResponseVec & data);
        bool initHandles(const std::vector<std::string> & urls,
                         CurlResponseVec & results);
        std::string                     userAgent_;
        std::string                     cookieFile_;
        bool                            redirect_;
        int                             maxFollow_;
        bool                            active_;
        int                             id_;
        int                             timeout_;
        bool                            useAlternateDNS_;
        std::string                     alternateDNS1_;
        std::string                     alternateDNS2_;
        static std::string              userAgentDefault_;
        static std::string              cookieFileDefault_;
        static bool                     redirectDefault_;
        static int                      maxFollowDefault_;
        static bool                     bGlobalInit_;
        static int                      timeoutDefault_;
        std::vector<CURL*>              handles_;
        CURLSH *                        share_;
    };
    /*@}*/
}

#endif

