/*
 * @Description: USERAPP
 * @Version: 1.0
 * @Autor: lishengyin
 * @Date: 2021-10-13 09:41:50
 * @LastEditors: lishengyin
 * @LastEditTime: 2022-01-11 12:34:12
 */
#pragma once

#include <iostream>
#include <signal.h>

// ZLMediaKit
#include "Util/logger.h"
#include "Util/NoticeCenter.h"
#include "Poller/EventPoller.h"
#include "Player/PlayerProxy.h"
#include "Rtmp/RtmpPusher.h"
#include "Common/config.h"
#include "Pusher/MediaPusher.h"
#include "Extension/Frame.h"
#include "Util/SqlPool.h"
#include "Network/TcpClient.h"
#include "Poller/Timer.h"
#include "TCPClient.h"
#include "inifile.h"

#include <gst/gst.h>
#include <vector>
#include <map>
#include <time.h>
#include "inference.h"
#include "DataSource.h"

// dataType
#include "SendLogin.h"
#include "NettyServerCommandEnum.h"
#include "NettyServerResultMsg.h"
#include "NettyClientResultMsg.h"
#include "SendLogin.h"
#include "NettyClientCommandEnum.h"
#include "InferData.h"
#include "PIDSClientResultMsg.h"
#include "PIDSServerResultMsg.h"
#include "CrowdednessConfig.h"
#include "CrowdednessTimeConfig.h"
#include "SendPassengerFlow.h"

#include "SendCarData.h"
#include "Notices.h"
#include "HttpClient.h"
#include "recorder.h"
#include "Cleaner.h"
#include "monitor.h"
#include "deviceState.h"
#include "Manager.h"
#include <httplib.h>

using namespace toolkit;
using namespace mediakit;
using namespace inifile;

using namespace std;

namespace MIVA
{  
    class UserApp
    {
    public:

        /**
         * @description: 创建对象
         * @param {*}
         * @return {std::shared_ptr<UserApp>} 智能指针
         * @author: lishengyin
         */    
        static std::shared_ptr<UserApp> CreateNew();
        UserApp();
        ~UserApp();

        /**
         * @description: 模块初始化
         * @param {string} appName 应用名
         * @return {int} 是否成功
         * @author: lishengyin
         */        
        int32_t Init(std::string appName);

        /**
         * @description: 释放数据
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void Destroy();

        /**
         * @description: 启动任务
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void StartTask();

        /**
         * @description: 获取数据
         * @param {*}
         * @return {*}
         */        
        int32_t GetNettyDatas();

        /**
         * @description: 赋值struct sockaddr
         * @param {sockaddr} *out
         * @param {char} *ip
         * @param {uint16_t} port
         * @return {*}
         * @author: lishengyin
         */        
        static void makeAddr(struct sockaddr *out,const char *ip,uint16_t port);
        
        /**
         * @description: 最终的结果运算
         * @param {uint32_t} noLoad 空载车厢载荷
         * @param {uint32_t} dynamicLoad 动态车厢载荷
         * @param {int} num 推理结果
         * @return {uint32_t} 运算结构
         * @author: lishengyin
         */        
        static uint32_t DataCalculation(uint32_t noLoad, uint32_t dynamicLoad, int num);

        /**
         * @description: 拥挤成都判定
         * @param {int} num 识别结果
         * @return {uint8_t} 拥挤程度 1-4
         * @author: lishengyin
         */        
        static uint8_t GradeDetermination(int num);
        
        /**
         * @description: 
         * @param {string} Pid
         * @return {*}
         */        
        static int GetAddrNum(std::string Pid);
    private:
        IniFile m_ini;
        std::string m_appName;
        const std::string m_configSrc = "../config/config.ini";
    private:
        // Natty
        std::string Netty_ip;
        int32_t Netty_port;
        std::string Netty_idName;

        // PIS
        std::string PIS_ip;
        int32_t PIS_port;
        std::string PIS_IdName;

        // Mysql
        std::string sql_ip;
        int32_t sql_port;
        std::string user;
        std::string password;
        std::string character;

        // Http
        std::string account;
        std::string pwd;
        std::string uri;
        std::string port;

        int device_id;
        int MemoryThreshold = 1024;
        bool play = false;
        bool start = true;
        bool enable = true;
    private:
        std::shared_ptr<TCPClient> m_tcpClient = NULL;
        std::shared_ptr<Inference> m_Infer = NULL;
        std::shared_ptr<HttpClient> m_httpClient = NULL;
        std::shared_ptr<recorder> m_recorder = nullptr;
        std::shared_ptr<Cleaner> m_Cleaner = nullptr;
        std::shared_ptr<monitor> m_monitor = nullptr;
        deviceState::Ptr m_deviceState = nullptr;
        Manager::Ptr m_manager = nullptr;

        Socket::Ptr m_udpClient = NULL;

        std::shared_ptr<InferInfo> m_InferInfo = NULL;

        Timer::Ptr m_timer0;
        Timer::Ptr m_timer1;
        Timer::Ptr m_timer2;
        Timer::Ptr m_timer3;
        Timer::Ptr m_timer4;
        Timer::Ptr m_timer5;
        Timer::Ptr m_timer6;
        

    private:

        /**
         * @description: 监听推理模块广播
         * @param {int} Source_id 数据源ID
         * @param {int} num 推理结果
         * @return {*}
         * @author: lishengyin
         */        
        void ListenInfer(int Source_id, int num);

        /**
         * @description: 监听Netty下发的数据
         * @param {Ptr} &pBuf 接受到的数据
         * @return {*}
         * @author: lishengyin
         */        
        void ListenNettyData(const Buffer::Ptr &pBuf);

        /**
         * @description: 监听PIS系统的数据
         * @param {Ptr} &buf 接受到的数据
         * @param {sockaddr} *addr socker信息
         * @return {*}
         * @author: lishengyin
         */        
        void ListenPISData(const Buffer::Ptr &buf, struct sockaddr *addr);

        /**
         * @description: 监听车厢关门广播
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void ListenClosed();

        /**
         * @description: 监听重启识别广播
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void ListenRelease();

        /**
         * @description: 监听推理数据广播
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void ListenInferData();

        /**
         * @description: 监听推理完成
         * @param {*}
         * @return {*}
         */        
        void ListenInferPer();

        /**
         * @description: 连接Netty
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void ConnectNetty();
        
        /**
         * @description: 上报数据到PIS
         * @param {*}
         * @return {*}
         * @author: lishengyin
         */        
        void ReportData();

        /**
         * 上报推理数据到Netty
         * @param {*}
         * @return {*}
         */    
        void ReportInferData();

        /**
         * 监听数据
         * @param {*}
         * @return {*}
         */    
        void MonitorData();

        /**
         * @description: 清理内除
         * @param {*}
         * @return {*}
         */        
        int32_t ClearMemory();
    };
}