#ifndef MapLib_h
#define MapLib_h

//#include "BindRoad.h"
#include "MapTypes.hpp"

namespace jf {
class MapLib {
   public:
    MapLib();
    ~MapLib() = default;

   public:
    bool GetLinkPreNxt(const HdLinkId &lLinkId, std::vector<HdLinkId> &vctliOutPreLinkIds, std::vector<HdLinkId> &vctliOutNxtLinkdIds);

    bool BFSLinks(const HdLinkId &from, double &ret, bool backward, bool &outFound, double outIterMetre, HdLinkId &outLink);
    bool HmmBindRoad(const BindRoadInput &input, BindRoadOutput &output);
    bool GetDataNearby(const Point &ptPoint, float fLonIntervalHalfMetre, float fLatIntervalHalfMetre, std::vector<HdLinkId> &vcthlOutLink);

    /**
     * @brief 初始化
     * @param strProjectPath：工程路径，如：/data/jfxoffline/
     * @param strMapConfigPath：mapConfig文件子路径（相对于工程路径），如：./maps/gj_tianjin/mapconfig.json
     * @return 无
     */
    void Init(const std::string &strProjectPath, const std::string &strMapConfigPath);

    /**
     * @brief 获取范围内（配置文件指定）和指定点接近的所有的Endpoint(按照距离排序)
     * @param ptPoint：输入点
     * @param vctptOutPoint：获取到的各个Endpoint上距离输入点最近的点，与vctleOutLinkEp一一对应
     * @param vctleOutLinkEp：获取到的各个Endpoint的集合，按照距离由近及远排序
     * @param vctdOutDistance：到各个Endpoint的直线距离
     * @return 成功：true，失败：false
     */
    bool GetNearEndpoints(const Point &ptPoint, std::vector<Point> &vctptOutPoint, std::vector<LinkEndpoint> &vctleOutLinkEp, std::vector<double> &vctdOutDistance);

    /**
     * @brief 获取范围内（配置文件指定）和指定点接近的所有的Endpoint(按照距离排序)
     * @param ptPoint：输入点
     * @param vctptOutPoint：获取到的各个Endpoint上距离输入点最近的点，与vctleOutLaneEp一一对应
     * @param vctleOutLinkEp：获取到的各个Endpoint的集合，按照距离由近及远排序
     * @param vctdOutDistance：到各个Endpoint的直线距离
     * @return 成功：true，失败：false
     */
    bool GetNearEndpoints(const Point &ptPoint, std::vector<Point> &vctptOutPoint, std::vector<LaneEndpoint> &vctleOutLaneEp, std::vector<double> &vctdOutDistance);

    /**
     * @brief 获取范和指定点最近的Endpoint
     * @param ptPoint：输入点
     * @param ptOutPoint：获取到的Endpoint上距离输入点最近的点
     * @param leOutEp：获取到的Endpoint
     * @param dOutDistance：到Endpoint的直线距离
     * @return 成功：true，失败：false
     */
    bool GetNearestEndpoint(const Point &ptPoint, Point &ptOutPoint, LinkEndpoint &leOutEp, double &dOutDistance);

    /**
     * @brief 获取范和指定点最近的Endpoint
     * @param ptPoint：输入点
     * @param ptOutPoint：获取到的Endpoint上距离输入点最近的点
     * @param leOutEp：获取到的Endpoint
     * @param dOutDistance：到Endpoint的直线距离
     * @return 成功：true，失败：false
     */
    bool GetNearestEndpoint(const Point &ptPoint, Point &ptOutPoint, LaneEndpoint &leOutEp, double &dOutDistance);

    /**
     * @brief 给定点所属与的Lanendpoint的集合
     * @param ptPoint：输入点
     * @param vctleOutLaneEp：输入点所属的LaneEndpoint的集合
     * @return 成功：true，失败：false
     */
    bool GetLocateEndpoints(const Point &ptPoint, std::vector<LaneEndpoint> &vctleOutLaneEp);

    /**
     * @brief 获得和当前点相连接的上一组Endpoint（仅限实际存在的车道）
     * @param leCurEndpoint：当前Endpoint
     * @param vctleOutPreEndpoint：于当前Endpoint相连的上一组Endpoint
     * @return 成功：true，失败：false
     */
    bool GetPreEndpoints(const LaneEndpoint &leCurEndpoint, std::vector<LaneEndpoint> &vctleOutPreEndpoint);

    /**
     * @brief 获得和当前点相连接的下一组Endpoint（包括实际存在的车道和可以从该车道便道可以到达的虚拟车道）
     * @param leCurEndpoint：当前Endpoint
     * @param vctleOutNextEndpoints：于当前Endpoint相连的下一组Endpoint
     * @return 成功：true，失败：false
     */
    bool GetNextEndpoints(const LinkEndpoint &leCurEndpoint, std::vector<LinkEndpoint> &vctleOutNextEndpoints);

    /**
     * @brief 获得和当前点相连接的下一组Endpoint（包括实际存在的车道和可以从该车道便道可以到达的虚拟车道）
     * @param leCurEndpoint：当前Endpoint
     * @param vctleOutNextEndpoints：于当前Endpoint相连的下一组Endpoint
     * @return 成功：true，失败：false
     */
    bool GetNextEndpoints(const LaneEndpoint &leCurEndpoint, std::vector<LaneEndpoint> &vctleOutNextEndpoints);

    /**
     * @brief 给定点所属与的Lane的集合
     * @param ptPoint：输入点
     * @param vcthlOutLink：输入点所属的Link的集合, 与vcthlOutLane一一对应
     * @param vcthlOutLane：输入点所属的Lane的集合, 与vcthlOutLink一一对应
     * @return 成功：true，失败：false
     */
    bool GetLocateLanes(const Point &ptPoint, std::vector<HdLinkId> &vcthlOutLink, std::vector<HdLaneId> &vcthlOutLane);

    /**
     * @brief 获得给定点到给定线的垂足
     * @param lLinkId：lnk的Id
     * @param nLaneSeqNum：车道序号
     * @param ptPoint：给定点
     * @param ptOutPoint：计算出的垂足点
     * @return 成功：true，失败：false
     */
    bool GetPerpendicularFoot(const HdLinkId &lLinkId, int nLaneNum, const Point &ptPoint, Point &ptOutPoint);

    /**
     * @brief 获得给定点到给定线的垂足
     * @param ptPoint：给定点
     * @param vctvdGeoLink：给定线
     * @param ptOutPoint：计算出的垂足点
     * @param dOutDistance：到该垂足点的距离
     * @return 成功：true，失败：false
     */
    bool GetPerpendicularFoot(const Point &ptPoint, const std::vector<std::vector<double>> &vctvdGeoLink, Point &ptOutPoint, double &dOutDistance);

    /**
     * @brief 获得给定点到给定线上最近的点（该线上实际存在的点，不是垂足）
     * @param ptPoint：给定点
     * @param vctvdGeoLink：给定线
     * @param ptOutPoint：距离给定点最近的点
     * @param dOutDistance：到该点的距离
     * @param outIndex：该点在整个线上的位置索引
     * @return 成功：true，失败：false
     */
    bool GetNearestDistance(const Point &ptPoint, const std::vector<std::vector<double>> &vctvdGeoLink, Point &ptOutPoint, double &dOutDistance, int &outIndex);

    /**
     * @brief 获取Link长度
     * @param lLinkId：link的Id
     * @param dOutLinkLength：获取的link的长度
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkLength(const HdLinkId &lLinkId, double &dOutLinkLength);

    /**
     * @brief 获取Link类型
     * @param lLinkId：lnk的Id
     * @param nOutLinkType：获取的link的类型
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkType(const HdLinkId &lLinkId, int &nOutLinkType);

    /**
     * @brief 获取Link起点方向角度
     * @param lLinkId：link的Id
     * @param dOutStartAngle：获取的link的起点方向角度
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkStartAngle(const HdLinkId &lLinkId, double &dOutStartAngle);

    /**
     * @brief 获取Link限速
     * @param lLinkId：link的Id
     * @param nOutSpeedLimit：获取的link的限速
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkSpeedLimit(const HdLinkId &lLinkId, int &nOutSpeedLimit);

    /**
     * @brief 获取Link限高限重等信息
     * @param lLinkId：link的Id
     * @param nLimitType：限制信息的类型
     * @param nOutLimitValue：获取的link的限高限重等信息
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkLimitValue(const HdLinkId &lLinkId, int nLimitType, int &nOutLimitValue);

    /**
     * @brief 获取Link等级
     * @param lLinkId：link的Id
     * @param nOutRank：获取的Link的等级
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkRank(const HdLinkId &lLinkId, int &nOutRank);

    /**
     * @brief 获取Link的上一组车道
     * @param lLinkId：lnk的Id
     * @param vctlOutPLinkId：获取的上一组车道的序号
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkPre(const HdLinkId &lLinkId, std::vector<HdLinkId> &vctlOutPLinkId);

    /**
     * @brief 获取Link的下一组车道
     * @param lLinkId：lnk的Id
     * @param vctlOutNLinkId：获取的下一组车道的序号
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkNext(const HdLinkId &lLinkId, std::vector<HdLinkId> &vctlOutNLinkId);

    /**
     * @brief 获取Link的下一组车道
     * @param lLinkId：lnk的Id
     * @param nLaneSeqNum：车道序号
     * @param vctlOutNLinkId：获取的下一组车道的序号
     * @return 成功 ：ture，失败：false
     */
    bool GetLinkNext(const HdLinkId &lLinkId, int nLaneSeqNum, std::vector<HdLinkId> &vctlOutNLinkId);

    /**
     * @brief 获取Link内的车道数
     * @param lLinkId：link的Id
     * @param nOutLanesCnt：获取的车道数
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneCnt(const HdLinkId &lLinkId, int &nOutLanesCnt);

    /**
     * @brief 获取Link内的车道数
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道序号
     * @param lOutLaneId：获取的车道号
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneId(const HdLinkId &lLinkId, int nLaneSeqNum, HdLaneId &lOutLaneId);

    /**
     * @brief 获取车道号
     * @param lLinkId：link的Id
     * @param lLaneId：车道中心线Id
     * @param nOutLaneSeqNum：车道号
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneNum(const HdLinkId &lLinkId, const HdLaneId &lLaneId, int &nOutLaneSeqNum);

    /**
     * @brief 获取车道类型
     * @param lLinkId：lnk的Id
     * @param nLaneSeqNum：车道序号
     * @param lOutLaneType：获取的车道类型
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneType(const HdLinkId &lLinkId, int nLaneSeqNum, int &nOutLaneType);

    /**
     * @brief 获取Lane的车道宽度
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道序号
     * @param dOutLaneWidth：获取的车道的宽度
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneWidth(const HdLinkId &lLinkId, int nLaneSeqNum, double &dOutLaneWidth);

    /**
     * @brief 获取Lane的车道边缘线Id
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道序号
     * @param bIsLeft：是否是左车道
     * @param lOutEdgeId：获取的车道序号
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneEdgeId(const HdLinkId &lLinkId, int nLaneSeqNum, bool bIsLeft, HdEdgeId &lOutEdgeId);

    /**
     * @brief 获取Lane的下一组车道
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道序号
     * @param vctlOutNLaneId：获取的下一组车道的序号
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneNext(const HdLinkId &lLinkId, int nLaneSeqNum, std::vector<HdLaneId> &vctlOutNLaneId);

    /**
     * @brief 获取车道中心线上的坐标点
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道中心线序号
     * @param vctvdOutGeolink：车道中心线坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneGeoLink(const HdLinkId &lLinkId, int nLaneSeqNum, std::vector<std::vector<double>> &vctvdOutGeoLink);

    /**
     * @brief 获取车道中心线上某个点的航向角
     * @param lLinkId：link的Id
     * @param lLaneId：车道中心线Id
     * @param ptInPoint：车道中心线附近的某个点
     * @param dOutAzimuth：航向角
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneAzimuth(const HdLinkId &lLinkId, const HdLaneId &lLaneId, const Point &ptInPoint, double &dOutAzimuth);

    /**
     * @brief 获取Link的车道边缘线数目
     * @param lLinkId：link的Id
     * @param nOutEdgeCnt：获取的车道边缘线的数目
     * @return 成功 ：ture，失败：false
     */
    bool GetEdgeCnt(const HdLinkId &lLinkId, int &nOutEdgeCnt);

    /**
     * @brief 获取车道边缘线Id
     * @param lLinkId：link的Id
     * @param nEdgeIdx：车道边缘线序号
     * @param lOutEdgeId：获取的车道边缘线ID
     * @return 成功 ：ture，失败：false
     */
    bool GetEdgeId(const HdLinkId &lLinkId, int nEdgeIdx, HdEdgeId &lOutEdgeId);

    /**
     * @brief 获取车道边缘线跨越属性
     * @param lLinkId：link的Id
     * @param lEdgeId：车道边缘线ID
     * @param nOutEdgeCross：获取的车道边缘线跨越属性
     * @return 成功 ：ture，失败：false
     */
    bool GetEdgeCross(const HdLinkId &lLinkId, HdEdgeId lEdgeId, int &nOutEdgeCross);

    /**
     * @brief 获取车道边缘线Color属性
     * @param lLinkId：link的Id
     * @param nEdgeNum：车道边缘线Num
     * @param nOutEdgeColor：获取的车道边Color属性
     * @return 成功 ：ture，失败：false
     */
    bool GetEdgeColor(const HdLinkId &lLinkId, HdEdgeId lEdgeId, int &nOutEdgeColor);

    /**
     * @brief 根据车道中心线获取他的边缘线上的跨越属性
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道中心线序号
     * @param bIsLeft：是否是左边界线
     * @param nOutCrossType：车道边缘线跨越属性
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneEdgeCrossType(const HdLinkId &lLinkId, int nLaneSeqNum, bool bIsLeft, int &nOutCrossType);

    /**
     * @brief 根据车道中心线获取他的边缘线上的坐标点
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道中心线序号
     * @param bIsLeft：是否是左边界线
     * @param vctvdOutGeolink：车道边缘线坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetLaneEdgeGeoLink(const HdLinkId &lLinkId, int nLaneSeqNum, bool bIsLeft, std::vector<std::vector<double>> &vctvdOutGeolink);

    /**
     * @brief 获取车道边缘线上的坐标点
     * @param lLinkId：link的Id
     * @param lEdgeId：边缘线ID
     * @param vctvdOutGeolink：车道边缘线坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetEdgeGeolink(const HdLinkId &lLinkId, HdEdgeId lEdgeId, std::vector<std::vector<double>> &vctvdOutGeolink);

    /**
     * @brief 获取指定的停止线的坐标
     * @param clLinkId：link的Id
     * @param nType：类型
     * @param vctvdOutGeolink：停止线坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetStopLineGeolink(const HdLinkId &clLinkId, int nType, std::vector<std::vector<double>> &vctvdOutGeolink);

    // /**
    //  * @brief 获取指定的交通指示牌的信息
    //  * @param clLinkId：link的Id
    //  * @param vctnOutType1：交通指示牌Type1
    //  * @param vctnOutType2：交通指示牌Type2
    //  * @param vctstOutText：交通指示牌Text
    //  * @param vctvdOutGeometry: 交通指示牌的坐标
    //  * @return 成功 ：ture，失败：false
    //  */
    // bool GetTrafficSign(const HdLinkId &clLinkId, std::vector<int> &vctnOutType1, std::vector<int> &vctnOutType2, std::vector<std::string> &vctstOutText, std::vector<std::vector<std::vector<double>>> &vctvvOutGeoArea);

    /**
     * @brief 获取指定的交通指示灯的坐标
     * @param clLinkId：link的Id
     * @param nLaneSeqNum：车道中心线序号
     * @param nType：类型
     * @param vctvdOutGeolink：交通指示灯坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetTrafficLightGeolink(const HdLinkId &clLinkId, int nLaneSeqNum, int nType, std::vector<std::vector<double>> &vctvdOutGeolink);

    /**
     * @brief 获取指定的上方障碍物的坐标
     * @param clLinkId：link的Id
     * @param nLaneSeqNum：车道中心线序号
     * @param nType：类型
     * @param vctvdOutGeolink：上方障碍物坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetOverHeadGeolink(const HdLinkId &clLinkId, int nLaneSeqNum, int nType, std::vector<std::vector<double>> &vctvdOutGeolink);

    /**
     * @brief 获取指定的交通指示牌的信息
     * @param clLinkId：link的Id
     * @param vctnOutShape：交通指示牌Shape
     * @param vctnOutType1：交通指示牌Type1
     * @param vctnOutType2：交通指示牌Type2
     * @param vctstOutText：交通指示牌Text
     * @param vctvdOutGeometry: 交通指示牌的坐标
     * @return 成功 ：ture，失败：false
     */
    bool GetTrafficSign(const HdLinkId &clLinkId, std::vector<int> &vctnOutShape, std::vector<int> &vctnOutType1, std::vector<int> &vctnOutType2, std::vector<std::string> &vctstOutText, std::vector<std::vector<std::vector<double>>> &vctvvOutGeoArea);

    /**
     * @brief 获取指定的交通指示牌的信息
     * @param cptPoint：坐标点
     * @param vctnOutShape：交通指示牌Shape
     * @param vctnOutType1：交通指示牌Type1
     * @param vctnOutType2：交通指示牌Type2
     * @param vctstOutText：交通指示牌Text
     * @param vctvvOutGeoArea: 交通指示牌的坐标
     * @return 成功 ：ture，失败：false
     */
    bool GetTrafficSign(const Point &cptPoint, std::vector<int> &vctnOutShape, std::vector<int> &vctnOutType1, std::vector<int> &vctnOutType2, std::vector<std::string> &vctstOutText, std::vector<std::vector<std::vector<double>>> &vctvvOutGeoArea);

    /**
     * @brief 获取指定的交通指示牌的坐标
     * @param clLinkId：link的Id
     * @param nShape：形状
     * @param vctvdOutGeometry：交通指示牌坐标点
     * @return 成功 ：ture，失败：false
     */
    bool GetTrafficSignGeometry(const HdLinkId &clLinkId, int nShape, std::vector<std::vector<double>> &vctvdOutGeometry);

    /**
     * @brief 车道是否包含指定的转向指示箭头
     * @param lLinkId：link的Id
     * @param nLaneSeqNum：车道中心线的序号
     * @param cArrowType：指示箭头的类型
     * @return 包含：true，不包含：false
     */
    bool IsLaneContainArrow(const HdLinkId &lLinkId, int nLaneSeqNum, char cArrowType);

    /**
     * @brief 转换坐标的形式
     * @param vctvdGeolink：转换源，double型的双层数组
     * @param vctptOutGeolink：转换结果：Point类型的单层数组
     * @return 均为true
     */
    bool ConvertGeolink(const std::vector<std::vector<double>> &vctvdGeolink, std::vector<Point> &vctptOutGeolink);

    /**
     * @brief 转换坐标的形式
     * @param vctptGeolink：转换源：Point类型的单层数组
     * @param vctvdOutGeolink：转换结果：double型的双层数组
     * @return 均为true
     */
    bool ConvertGeolink(const std::vector<Point> &vctptGeolink, std::vector<std::vector<double>> &vctvdOutGeolink);

    /**
     * @brief 获取LaneEndpoint上的轨迹点
     * @param leEndpoint：指定的LaneEndpoint
     * @param vctvdOutGeolink：轨迹点
     * @param bManageTile：目前没有使用
     * @return 均为true
     */
    bool GetGeoLink(const LaneEndpoint &leEndpoint, std::vector<std::vector<double>> &vctvdOutGeolink, bool bManageTile = false);

    /**
     * @brief 获取Link上的轨迹点
     * @param leEndpoint：指定的LaneEndpoint
     * @param vctvdOutGeolink：轨迹点
     * @return 均为true
     */
    bool GetGeoLink(const HdLinkId &lLinkId, std::vector<std::vector<double>> &vctvdOutGeolink);
};
};  // namespace jf

#endif
