#pragma once
#include <unordered_map>
#include <map>
#include <deque>
#include <iostream>
#include "SyncTimeMsg.h"
#include "Position.h"
#include "Common.h"
#include "SyncTime.h"
#include "SyncHelper.h"
#include "TagMsg.h"

using namespace std;

namespace HostServer{
	
    class SyncManager
    {
		struct SyncTimeMsgItem
		{
			unsigned short SyncNum;
			unordered_map<unsigned long long, SyncTimeMsg> SyncTimeMsgs;
		};
		struct SyncTimeItem
		{
			unsigned short SyncNum;
			unordered_map<unsigned long long, SyncTime> HistSync;
		};

		CRITICAL_SECTION m_csSyncTime;
		CRITICAL_SECTION m_csCalcLiner;

		bool isOutputLog;
		string logDir;
    public:
        SyncManager();
		~SyncManager();

        //************************************
        // Description: 用于初始化所有成员
        // Method:      init
        // Returns:     void
        //************************************
        void init();

        //************************************
        // Description: 用于解析时间同步msg中的内容
        // Method:      analyzeMsg
        // Returns:     void
        // Parameter:   SyncTimeMsg & msg 从socket获取的消息
        //************************************
        void analyzeSyncMsg(SyncTimeMsg &msg);

        //************************************
        // Description: 更新距离信息
        // Method:      updateDistance
        // Returns:     void
        // Parameter:   unsigned int localId 当前分站号
        // Parameter:   unsigned char localAntNum 当前分站的天线号
        // Parameter:   unsigned int upperId 上级分站号
        // Parameter:   unsigned char uppderAntNum 上级分站的天线号
        // Parameter:   int d 距离
        //************************************
        void updateDistance(unsigned int localId, unsigned char localAntNum, unsigned int upperId, unsigned char uppderAntNum, double d);

        //************************************
        // Description: 更新anchor信息
        // Method:      updateAnchor
        // Returns:     void
        // Parameter:   unsigned int localId 当前分站号
        // Parameter:   unsigned char localAntNum 当前分站的天线号
        // Parameter:   int x
        // Parameter:   int y
        // Parameter:   int z
        //************************************
        void updateAnchor(unsigned int localId, unsigned char localAntNum, double x, double y, double z);

        //************************************
        // Description: 删除anchor
        // Method:      deleteAnchor
        // Returns:     void
        // Parameter:   unsigned int localId 当前分站号
        // Parameter:   unsigned char localAntNum 当前分站的天线号
        //************************************
        void deleteAnchor(unsigned int localId, unsigned char localAntNum);

		// unsigned long long代表anchor编码 ID+AntNum
        unordered_map<unsigned long long, Position> _anchors; 
        // unsigned long long 代表anchor编码 ID+AntNum
        unordered_map<unsigned long long,unordered_map<unsigned long long, double>> _distance; 

		// with root
        // 使用_syncTimeMsgs[SyncNum][LocalIdCode]访问对应的SyncTimeMsg,即同步时间消息
		unordered_map<unsigned long long, deque<SyncTimeMsgItem>> _syncTimeMsgs;

        // 使用_historySync[SyncNum][LocalIdCode]访问对应的SyncTime，即计算后的时间同步
		unordered_map<unsigned long long, deque<SyncTimeItem>> _historySync;

        //************************************
        // Description: 根据Tag的记录和历史msg，利用线性插值算法计算Tag的预估时间
        // Method:      calTimeByLinar
        // Returns:     unsigned long long 
        // Parameter:   unsigned long long tagReceiveTime tag的接收时间
        // Parameter:   unsigned short SyncNum  接收tag时的时间同步编号
        // Parameter:   unsigned long long localIdCode 接收tag的anchorID编码
        //************************************
        unsigned long long calTimeByLinar(TagMsg &tag);
		//************************************
		// Method:    updateSync
		// Returns:   bool
		// Parameter: unsigned long long rootIdCode
		// Parameter: unsigned short SyncNum
		// Parameter: unsigned long long localIdCode
		//************************************
		bool updateSync(unsigned long long rootIdCode, int idx, unsigned short SyncNum, unsigned long long localIdCode);
		int FindSyncTimeMsg(unsigned long long rootIdCode, unsigned short SyncNum);
		int FindHisSyncTime(unsigned long long rootIdCode, unsigned short SyncNum);

		void SetOutputLog(bool log){	this->isOutputLog = log;}
		bool IsOutputLog() const {return isOutputLog;}
    };
}