/*
 * Copyright (c) 2021 Huawei Technologies Co.,Ltd.
 *
 * CM is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * cm_client.h
 *
 *
 * IDENTIFICATION
 *    include/cm/cm_client/cm_client.h
 *
 * -------------------------------------------------------------------------
 */
#ifndef CM_CLIENT_H
#define CM_CLIENT_H

#include <queue>
#include <sys/un.h>
#include "cm/cm_msg.h"
#include "cm/cm_misc_base.h"
#include "cm_client_api.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CM_CLIENT_MSG_VER 1

#define NO_STAT_CHANGED 0
#define STAT_CHANGED    1

#define CLIENT_USEC_TO_NSEC     (1000)
#define CLIENT_INVALID_SOCKET   (-1)
#define CLIENT_RES_DATA_TIMEOUT (5)
#define CLIENT_SEND_CHECK_INTERVAL (300 * 1000)
#define CLIENT_RECV_CHECK_INTERVAL (300 * 1000)
#define CLIENT_CHECK_CONN_INTERVAL (200 * 1000)

typedef struct MsgPackageSt {
    char *msgPtr;
    size_t msgLen;
} MsgPackage;

typedef struct SockAddrSt {
    struct sockaddr_un addr;
    socklen_t addrLen;
} SockAddr;

typedef struct ConnAgentSt {
    int sock;
    volatile bool isClosed;
    uint32 resInstanceId;
    CmNotifyFunc callback;
    timespec recvTime;
    pthread_rwlock_t rwlock;
} ConnAgent;

typedef struct SendMsgQueueSt {
    std::queue<MsgPackage> sendQueue;
    pthread_mutex_t lock;
    pthread_cond_t cond;
} SendMsgQueue;

typedef struct InitFlagSt {
    bool initSuccess;
    pthread_mutex_t lock;
    pthread_cond_t cond;
} InitFlag;

typedef struct LockFlagSt {
    uint32 error;
    uint32 ownerId;
    pthread_mutex_t condLock;
    pthread_mutex_t optLock;
    pthread_cond_t cond;
} LockFlag;

typedef struct ClientLockResultSt {
    uint32 error;
    uint32 ownerId;
} ClientLockResult;

typedef struct {
    LockFlag lockFlag;
    InitFlag initFlag;
    ConnAgent agentConnect;
    SendMsgQueue sendMsg;
    OneResStatList clientStatusList;
    pthread_t conThreadId;
    pthread_t sendThreadId;
    pthread_t recvThreadId;
} ClientCtx;

status_t CreateConnectAgentThread(void);
status_t CreateSendMsgThread(void);
status_t CreateRecvMsgThread(void);

#ifdef __cplusplus
}

status_t PreInit(uint32 instanceId, const char *resName, CmNotifyFunc func, bool *isFirstInit);
void ShutdownClient();
void AllocClientMemory();
void FreeClientMemory();
void SendMsgApi(char *msgPtr, size_t msgLen);
bool &GetIsClientInit();
LockFlag *GetLockFlag();
InitFlag *GetInitFlag();
OneResStatList *GetClientStatusList();
status_t SendInitMsg(uint32 instanceId, const char *resName);
bool SendInitMsgAndGetResult(const char *resName, uint32 instId);
ClientLockResult SendLockMsgAndWaitResult(char *msgPtr, uint32 msgLen);

#endif
#endif // CM_CLIENT_H
