/**
 * Anatole SCHRAMM-HENRY
 * Updated on 12/07/2020
 */
#ifndef HTTPCLIENT_H
#define HTTPCLIENT_H

#include <ESP8266WiFi.h>
#include "HttpConstants.h"
#include "Dictionary.h"

namespace HttpClientHelper
{
  
}

class HttpClient : public WiFiClient, public HttpConstants
{
	public:
    enum HttpQueryStatus { SUCCESS = 0, ERR_CONN, ERR_CONN_MAX_RETRY, UNKNOWN_HTTP_METHOD };
    
    HttpClient(const char *address, uint16_t port = 80, uint32_t timeout = 5000);
    HttpClient(const char *address, const char *resource, uint16_t port = 80, uint32_t timeout = 5000);

    HttpClient(const HttpClient &object);
    virtual ~HttpClient();

    HttpQueryStatus sendHttpQuery(const char *resource,
    HttpRequestMethod method = HttpRequestMethod::GET,
    Dictionary<DictionaryHelper::StringEntity> *getData = NULL,
    Dictionary<DictionaryHelper::StringEntity> *postData = NULL, 
    Dictionary<DictionaryHelper::StringEntity> *headerData = NULL);
    
    HttpQueryStatus sendHttpQuery(HttpRequestMethod method = HttpRequestMethod::GET,
    Dictionary<DictionaryHelper::StringEntity> *getData = NULL,
    Dictionary<DictionaryHelper::StringEntity> *postData = NULL,
    Dictionary<DictionaryHelper::StringEntity> *headerData = NULL);
    void keepAlive(boolean enabled);
    void setMaxRetries(int16_t retries);
    int16_t getMaxRetries(void) const;
    uint16_t retriesCount(void) const;
    void resetRetriesCount(void);
    //10s is the default timeout
    HTTP_CODE isReplyAvailable(uint16_t timeout = 10000);
    
    uint16_t readHttpBody(uint8_t *buffer, uint32_t size);
	protected:
	private:
    enum ConnectionStatus { NO_ATTEMPT = 0, SUCCESSFUL, FAILED };

    boolean connectByHostOrIp();
    void sendUriWithGetParams(Dictionary<DictionaryHelper::StringEntity> *data);
    void sendPostData(Dictionary<DictionaryHelper::StringEntity> *data);
    void sendHeader(HttpMIMEType contentType = HttpMIMEType::UNKNOWN_MIME, uint64_t contentLength = 0, Dictionary<DictionaryHelper::StringEntity> *headerData = NULL, HttpVersion httpVersion = HttpVersion::HTTP_1_1);
    uint64_t computeBodyLength(Dictionary<DictionaryHelper::StringEntity> *data);
    
    ConnectionStatus _connectionStatus = NO_ATTEMPT;
    char *_resource = NULL;
    const char *_pAddress;
    uint16_t _port;
    boolean _keepAlive = false;
    int16_t _maxRetries = -1;
    uint16_t _retries = 0;
    boolean _isIp = false;
    HTTP_CODE _httpCode = HTTP_CODE::UNDEFINED_CODE;
    boolean _httpCodeParsed = false;
};

#endif //HTTPCLIENT_H

/*
 * TCP status codes :
 * enum tcp_state {
  CLOSED      = 0,
  LISTEN      = 1,
  SYN_SENT    = 2,
  SYN_RCVD    = 3,
  ESTABLISHED = 4,
  FIN_WAIT_1  = 5,
  FIN_WAIT_2  = 6,
  CLOSE_WAIT  = 7,
  CLOSING     = 8,
  LAST_ACK    = 9,
  TIME_WAIT   = 10
};
 */
