/** \file
 *
 *  Contains the DataOverHttps class declaration.
 *
 *  DataOverHttps.h should only be included by DataOverHttps.cpp
 *  Other classes should include DataOverHttpsIF.h
 *
 *  Copyright (c) 2013 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 */

#ifndef DATAOVERHTTPS_H
#define DATAOVERHTTPS_H

#include "component/AsyncComponent.h"
#include "data/StrValue.h"
#include "logger/Logger.h"
#include "utils/Timestamp.h"
#include "utils/FlexArray.h"
#include "DataOverHttpsIF.h"

#include <stdint.h>
#include <openssl/ssl.h>

class UniversalDataReader;
class UniversalDataWriter;

#define MAX_DOWNLINK_MSG_BYTES 340L
#define MAX_UPLINK_MSG_BYTES 270L

/**
 *  Provides software interface for sending sbds over the https
 *  when an https connection is available.
 *
 *  DataOverHttps.h should only be included by DataOverHttps.cpp
 *  Other classes should include DataOverHttpsIF.h
 *
 *  \ingroup modules_sensor
 */
class DataOverHttps: public AsyncComponent
{
public:

    DataOverHttps( const Module* module );

    virtual ~DataOverHttps();

    virtual void run();

    virtual void initialize();

    virtual void uninitialize();

    /// Should return [myNamespace]::SIMULATE_HARDWARE, or [myNamespace]::POWER, etc
    virtual ConfigURI getConfigURI( ConfigOption configOption ) const;

private:

    // Note that the copy constructor below is private and not given a body.
    // Any attempt to call it will return a compiler error.
    DataOverHttps( const DataOverHttps& old ); // disallow copy constructor

    // Slate outputs
    UniversalDataWriter* communicationsWriter_;
    DataWriter* connectionStatusWriter_;

    // Slate inputs
    DataReader* radioSurfacePowerReader_;

    /// Configuration readers
    ConfigReader* sendDataToShoreCfgReader_;
    ConfigReader* connectionTimeoutCfgReader_;
    ConfigReader* periodCfgReader_;
    ConfigReader* timeoutCfgReader_;
    ConfigReader* verbosityLevelCfgReader_;

    /// Async thread cycle period
    static const Timespan PERIOD;

    bool debug_;
    int verbosity_; // A config setting you can use to increase or decrease the amount of (DEBUG) messages being written to the syslog

    bool sendDataToShore_;
    bool wasConnected_;
    float connectionTimeout_;
    float period_;
    float timeout_;
    Timestamp connectStart_;
    Timestamp lastPoll_;
    Timestamp lastComms_;
    bool radioSurfaceActive_;

    StrValue dashIP_;
    StrValue dashPath_;
    StrValue dashPort_;
    int dashSSL_;
    StrValue imei_;
    StrValue imeiPassword_;
    StrValue keyText_;
    Str headerStart_;
    Str contentStart_;

    struct addrinfo* addrinfo_;
    int socket_;
    SSL* sslHandle_;
    SSL_CTX* sslContext_;
    char sslErrBuf_[120];

    // initialize vehicle config variables
    bool loadParams( void );
    bool readConfig();

    enum DataState
    {
        TCP_CONNECT,     // 0
        TCP_CONNECTING,  // 1
        SSL_CONNECT,     // 2
        SSL_CONNECTING,  // 3
        DATA_WRITE,      // 4
        DATA_WRITING,    // 5
        DATA_READ,       // 6
        DISCONNECT,      // 7
        DISCONNECTED,    // 8
    } dataState_;

    enum KeyType
    {
        KEY_UNKNOWN = -1,
        KEY_BUSY,        // 0
        KEY_FILE,        // 1
        KEY_FILENAME,    // 2
        KEY_FILESIZE,    // 3
        KEY_MOMSN,       // 4
        KEY_MTMSN,       // 5
        KEY_VEHICLE,     // 6
        KEY_COUNT,
    };

    static const char* const KEY_TYPE_STRS[KEY_COUNT];

    static KeyType Str2KeyType( const char* const keyTypeStr );

    static bool ParseDataRead( char** data, KeyType &key, char** value );

    bool busy_;
    char* outgoing_;
    size_t outgoingSize_;

    static const int BUFFER_SIZE = 2048; // Big enough to contain Tomcat err msgs
    char buffer_[BUFFER_SIZE];
    char filename_[BUFFER_SIZE];
    char decoded_[BUFFER_SIZE];
    size_t decodedSize_;

    int bufferPos_;
    int dataStart_;
    int dataSize_;

    DataState tcpConnect();
    DataState tcpConnecting();
    DataState sslConnect();
    DataState sslConnecting();
    DataState dataWrite();
    DataState dataWriting();
    DataState dataRead();
    DataState disconnect();

    /// Name of file currently being sent to shore
    Str sendFilename_;

    /// Identity of last packet received from shore
    Str lastMtmsn_;

    // True if a command has been received from shore since the last time power was applied
    bool cmdReceived_;

};

#endif /*DATAOVERHTTPS_H*/
