#ifndef adasMapParser_h
#define adasMapParser_h

#include <iostream>
#include <string>
#include <vector>

#include "AdasTypes.h"
#include "HdTypes.h"
#include "SdTypes.h"

using namespace std;

namespace jf {
namespace adas {
typedef map<SdNodeId, SdNode> MapIdNode;
typedef map<RoadId, BaseWay> MapIdWay;
// typedef shared_ptr<MapIdWay> SpMapIdWay;

class AdasMapParser {
   public:
    template <typename boundCallbackType, typename nodeCallbackType, typename wayCallbackType, typename relationCallbackType>
    void Parse(const std::string &file_path, nodeCallbackType nc, wayCallbackType wc, boundCallbackType bc, relationCallbackType rc) {
        MapIdNode mapIdNode = {};
        MapIdWay mapIdWay = {};
        ShpBound stBound = {180, -180, 90, -90};

        // removeMapIdWay(file_path);

        // parse map data
        ParseAll(file_path, mapIdNode, mapIdWay, stBound);

        // update speed limit
        // updateSpeedLimit(file_path, mapIdNode);

        int i = 0;
        for (auto &node : mapIdNode) {
            ++i;
            // jf_log_info("node percent : {}%", (i / float(mapIdNode.size())) * 100);
            nc(node.second);
        }

        i = 0;
        for (auto &way : mapIdWay) {
            ++i;
            // jf_log_info("way percent : {}%", (i / float(mapIdWay.size())) * 100);
            wc(way.second);
        }

        bc(stBound);
    }

   private:
    void ParseAll(const string &strPath, MapIdNode &mapIdNode, MapIdWay &mapIdWay, ShpBound &stBound);

   private:
    void ParseJunction(const string &strPath, map<JfDataId, Junction> &mapIdJunction);
    void ParseRoad(const string &strPath, const map<JfDataId, Junction> &mapIdJunction, map<JfDataId, Road> &mapIdRoad, ShpBound &stBound);
    void ParseRADAS(const string &strPath, map<JfDataId, Road> &mapIdRoad);

    void ParseSpeed(const string &strPath, map<JfDataId, Speed> &mapIdSpeed);
    void ParseIndFacility(const string &strPath, const map<JfDataId, Speed> &mapIdSpeed, map<JfDataId, Road> &mapIdRoad);

    void MakeSdData(const map<JfDataId, Road> &mapIdRoad, MapIdNode &mapIdNode, MapIdWay &mapIdWay);

    void GetTids(const std::vector<std::vector<double>> &vctvdGeoLink, std::vector<TileId> &vctOutTids);

    template <typename numType>
    void AnalyseStrNums(const string &strId, vector<numType> &vctNums) {
        if (strId.length() == 0) {
            return;
        }

        string flag = ";";
        if (strId.find(flag, 0) != string::npos) {
            int position = 0;
            int lastPosition = position;
            // 查找“|”出现的所有位置，并解析
            while ((position = strId.find_first_of(flag, position)) != string::npos) {
                string id = strId.substr(lastPosition, 10);
                vctNums.push_back(atoll(id.c_str()));
                ++position;
                lastPosition = position;
            }
            string id = strId.substr(lastPosition, 10);
            vctNums.push_back(atoll(id.c_str()));
        } else {
            vctNums.push_back(atoll(strId.c_str()));
            return;
        }
    }

    int Factorial(int n);
};

}  // namespace adas

}  // namespace jf

#endif