/*
#  $Id$
# -----------------------------------------------------------------------------
#  The part of 'VideoNEXT MediaClient SDK'
# -----------------------------------------------------------------------------
#  Author: Petrov Maxim, 03/04/2009
#  Edited by:
#  QA by:
#  Copyright: videoNEXT LLC
# -----------------------------------------------------------------------------
*/

#ifndef MEDIA_CLIENT_IMPL_H                                                                                            
#define MEDIA_CLIENT_IMPL_H

#include <vector>
#include "NetIO.h"
#include "MediaClient.h"
#include "MediaStreamHandler.h"
#include "vn_client.h"

#define DEFAULT_TIMEOUT 60000

namespace videonext { namespace media {

struct MediaClientImpl
{
   MediaClientImpl()
      : timeout(DEFAULT_TIMEOUT), ctx_(NULL) {}

   ~MediaClientImpl()
   {
       if(ctx_) {
           vn_client_destroy(ctx_);
           ctx_ = NULL;
       }
   }

   void processXMLRequest(ResultStatus *result, const std::string &req, bool clearParams = true);

   void reset()
   {
      masterAddress.clear();
      sessionID.clear();
      username.clear();
      userID.clear();
      roleID.clear();
      roles.clear();
      objectsSets.clear();
      if(ctx_) {
          vn_client_destroy(ctx_);
          ctx_ = NULL;
      }
   }

   std::map<std::string, std::string> xmlParseMap; /// map for xml parsing, storing here current parse state

   std::string masterAddress;
   unsigned masterPort;
   std::string sessionID;
   std::string username;
   std::string userID;
   std::string roleID;
   std::map<std::string/*role id*/, Role> roles;
   std::map<std::string/*set id*/, MediaObjectsSet> objectsSets;
   unsigned timeout;
   DynaParams nodes;
   DynaParams serverInfo;
   vn_client_context_t* ctx_;
};


/** 
 * Performs ptz command
 * 
 * @param result 
 * @param mediaObject 
 * @param command comand in verbal form "left|right|up|down|downleft|upright|downright|upleft|in|out"
 */
void performPTZCommand(ResultStatus *result,
                       MediaObject *mediaObject,
                       const std::string &mode,
                       const std::string &command);

void getCredentials(const std::string &password, const std::string &encKey, char *result);


#define SET_RESULT_STATUS(result, errorcode, format_str, ...)           \
{                                                                       \
   char err_str[1024];                                                  \
                                                                        \
   snprintf(err_str, sizeof err_str, format_str,  ##__VA_ARGS__);       \
                                                                        \
   result->errorCode = errorcode;                                       \
   result->errorString = err_str;                                       \
}

class PushMediaClient
{
public:
   PushMediaClient();

   ~PushMediaClient();

   void initStream(ResultStatus *result, const std::string &hwid, const std::string& objid);

   void initRTSPStream(ResultStatus *result, const std::string &url);

   void registerDevice(ResultStatus *result, std::string* registeredObjId, const std::string &hwid,
                       const std::string &name, const std::string &telnum, const std::string &mediaFormat);

   void postFrame(ResultStatus *result, unsigned char *data, unsigned size, const DynaParams *headers);


private:
   int socket_;
   std::string objid_;
   std::string node_;
   char *responseBuffer_;
   unsigned int responseBufferSize_;
};


void url_split(char *proto, int proto_size,
               char *authorization, int authorization_size,
               char *hostname, int hostname_size,
               int *port_ptr,
               char *path, int path_size,
               const char *url);

void tokenize(const std::string& str, const std::string& delimiters, std::vector<std::string> *tokens);

int datetimeToTimeval(const char *datetime, struct timeval &tv);

std::string unixtsToDatetime(time_t unixts);

}}

#endif
