#ifndef __JFXMAP_BOSCH_MAPINTERFACE_HPP_
#define __JFXMAP_BOSCH_MAPINTERFACE_HPP_

#include "HdLib.h"
#include "InterfaceDefine.hpp"

namespace jf {

class MapInterface {
   public:
    MapInterface(const std::string& strPrjPath, const std::string& strCfgPath, int nTgtLen);
    ~MapInterface();

   public:
    bool GetMapData(const Adma& adAdma, MapData& mdOutMapData);

   private:
    enum LanePriority {
        Straight = 0,    // 直行优先
        LeftFirst = 1,   // 左转/左掉头/左弯/左合流优先
        RightFirst = 2,  // 右转/右掉头/右弯/右合流优先
    };

    bool MakeRoad(const Adma& adAdma, const HdLinkId& liLinkId, const HdLaneId& liLaneId, double dBroadDis, Road& rdOutRoadData);
    bool MakeGnss(const Adma& adAdma, uint64_t lMapCostTime, Gnss& gnOutGnss);
    bool GetFutureLinks(const Adma& adAdma, const HdLinkId& lLinkId, const HdLaneId& liLaneId, double dBroadDis, LanePriority& nInOutLanePrior, double& dOutToHeadDis, double& dOutToTailDis, std::vector<HdLinkId>& vctnOutFutureLinkId,
                        std::vector<HdLaneId>& vctliOutFutureLaneId, std::vector<double>& vctdOutRealLength);
    void MakeRoad(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, bool bIsChkPast, bool bIsChkFuture, double dToHeadDisFix, double dToTailDisFix, double dBroadDis, LanePriority nLanePrior, Road& rdOutRoadData);
    void MakeRoadLink(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior,
                      std::vector<RoadLink>& vctrlOutRoadLink);
    void MakeStopLine(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, StopLine& slOutStopLine);
    void MakePedestrianCrossing(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior,
                                PedestrianCrossing& pcOutPedestrianCrossing);
    void MakeCrossing(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, Crossing& crOutCrossing);
    void MakeRamp(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, Ramp& rmOutRamp);
    void MakeChange(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, Change& cgOutChange);
    void MakeSpeed(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, Speed& spOutSpeed);
    void MakeTrafficLight(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior,
                          TrafficLight& tlOutTrafficLight);
    void MakeRSU(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, RSU& rsOutRSU);
    void MakeTunnel(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior, Tunnel& tnOutTunnel);
    void MakeDashSolidChangeDis(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, LanePriority nLanePrior,
                                double& dOutDashSolidDis);

    void ConvertPoint3D(const Point& ptFrom, Point3D& ptTo);
    void ConvertPoint3D(const std::vector<double>& vctdFrom, Point3D& ptTo);
    void ConvertGeoLink(const std::vector<std::vector<double>>& vctvdFrom, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, std::vector<Point3D>& vctptTo);
    void ConvertEdgeCross(const HdEdge& heEdge, uint8_t& nOutCross);
    void GetPosInGeoLink(const Point& ptPos, const std::vector<std::vector<double>>& vctvdGeoLink, double& dOutToHeadDis, double& dOutToTailDis);
    void GetPosInGeoLink(const Point& ptPos, const std::vector<std::vector<double>>& vctvdGeoLink, bool bIsChkFuture, Point& ptOutFoot, int& nOutNearestIndex);
    void GetPosInGeoLink(const Point& ptPos, const std::vector<std::vector<double>>& vctvdGeoLink, bool bIsChkFuture, Point& ptOutFoot, int& nOutNearestIndex, double& dOutToHeadDis, double& dOutToTailDis);
    void GetLenPointAndIndex(double dLength, const std::vector<std::vector<double>>& vctvdGeoLink, bool bIsChkFuture, Point& ptOutLenPoint, int& nOutNearestIndex);
    void GetPosInHdLane(const Point& ptPos, const std::vector<std::vector<double>>& vctvdGeoLink, double& dOutToHeadDis, double& dOutToTailDis);
    bool IsBroad(double dPastLength, const HdLink* cphlLink, const HdLaneId& liLaneId, const Point& ptStartGeoFoot, int nStartGeoIndex, const Point& ptEndGeoFoot, int nEndGeoIndex, double dBroadDis, const Point& ptTargetPoint, double& dOutReportDis);
    double GetLaneAngle(const HdLinkId& liLinkId, const HdLaneId& liLaneId, bool bIsStart);
    bool GetNextLinkIdLaneId(const HdLinkId& chlCurLinkId, const HdLaneId& chlCurLaneId, double dLastAngle, LanePriority& nInOutLanePrior, HdLinkId& liOutNxtLinkId, HdLaneId& liOutNxtLaneId);
    void SimplifyPoint(std::vector<Point3D>& vctvdGeoLink, int nMaxPoints);

   private:
    ShPtr_HdLib m_spHdLib;
    int m_nTgtLen;
    double m_dMinPointsDis;
};

}  // namespace jf

#endif