//
//  DMKMapView.h
//  DMKMap
//
//  Created by yunfei on 2025/3/18.
//

#import <UIKit/UIKit.h>
#import "DMKType.h"
#import "DMKGeometry.h"
#import "DMKAnnotation.h"
#import "DMKAnnotationView.h"
#import "DMKOverlay.h"
#import "DMKOverlayRenderer.h"

#if __has_include(<DMKBaseSDK/DMKBaseConfigDefine.h>)
#import <DMKBaseSDK/DMKBaseConfigDefine.h>
#elif __has_include(<DMKDriverNavSDK/DMKBaseConfigDefine.h>)
#import <DMKDriverNavSDK/DMKBaseConfigDefine.h>
#else
#import <DMKBaseConfigSDK/DMKBaseConfigDefine.h>
#endif

NS_ASSUME_NONNULL_BEGIN

@protocol DMKMapViewDelegate;

@interface DMKMapView : UIView

/// 地图View的Delegate
@property (nonatomic, weak) id<DMKMapViewDelegate> delegate;

/// 是否显示路况，路况在zoomLevel>=10和<=18时候才会显示，默认为NO
@property (nonatomic, assign, getter = isShowTraffic) BOOL showTraffic;

/// 是否支持滚动，默认为YES
@property (nonatomic, assign, getter = isScrollEnabled) BOOL scrollEnabled;

/// 是否支持缩放，默认为YES
@property (nonatomic, assign, getter = isZoomEnabled) BOOL zoomEnabled;

/// 是否显示罗盘，默认为YES，只有在导航模式下生效
@property (nonatomic, assign, getter = isShowsCompass) BOOL showsCompass;

/// 控制存在地图俯仰角或3D导航时的旋转手势 默认YES
@property (nonatomic, assign, getter = isRotateEnabled) BOOL rotateEnabled;

/// 在当前缩放级别下, 基于地图中心点, 1 screen point 对应的距离(单位是米)
@property (nonatomic, readonly) CGFloat metersPerPointForCurrentZoomLevel;

/// 当前地图的中心点经纬度坐标
@property (nonatomic, assign) CLLocationCoordinate2D centerCoordinate;

/// 当前地图的经纬度范围，设定的该范围可能会被调整为适合地图窗口显示的范围
@property (nonatomic, assign) DMKCoordinateRegion region;

/// 当前地图可见范围的map rect
@property (nonatomic, assign) DMKMapRect visibleMapRect;

/// 缩放级别[4，20]
@property (nonatomic, assign) NSInteger zoomLevel;

/// 是否显示用户位置，默认为YES
@property (nonatomic, assign, getter = isShowsUserLocation) BOOL showsUserLocation;

/// 定位用户位置的模式，如果设置跟随模式 ，则默认设置用户位置显示
@property (nonatomic) DMKUserTrackingMode userTrackingMode;

/// 已添加标注的数组
@property (nonatomic, readonly) NSArray *annotations;

/// 已添加Overlay的数组
@property (nonatomic, readonly) NSArray *overlays;


- (instancetype)init NS_UNAVAILABLE;

- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;

#warning 必需在初始化之前调用<展示 + 同意>
/**
 更新App是否显示隐私弹窗的状态，隐私弹窗是否包含滴滴SDK隐私协议内容的状态.
 @param showStatus 弹窗展示状态
 @param constainStatus 包含滴滴隐私协议状态
 */
+ (void)updatePrivacyAgreementShow:(DMKPrivacyAgreementShowStatus)showStatus constainStatus:(DMKPrivacyAgreementContainStatus)constainStatus;

/**
 更新用户授权滴滴SDK隐私协议状态
 @param agreeStatus 隐私授权状态
 */
+ (void)updatePrivacyAgreementAgree:(DMKPrivacyAgreementAgreeStatus)agreeStatus;

/**
 * @brief 初始化方法
 * @param frame view的frame
 * @param language 地图语言
 */
- (instancetype)initWithFrame:(CGRect)frame withLanguage:(DMKMapLanguage)language;

/**
 * @brief 设定地图中心点经纬度
 * @param centerCoordinate 要设定的地图中心点经纬度
 * @param animated 是否采用动画效果
 */
- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate animated:(BOOL)animated;

/**
 * @brief 设定当前地图的region
 * @param region 要设定的地图范围，用经纬度的方式表示
 * @param animated 是否采用动画效果
 */
- (void)setRegion:(DMKCoordinateRegion)region animated:(BOOL)animated;

/**
 * @brief 根据当前地图视图frame的大小调整region范围，返回适合当前地图frame的region，调整过程中当前地图的中心点不会改变
 * @param region 要调整的经纬度范围
 * @return 调整后的经纬度范围
 */
- (DMKCoordinateRegion)regionThatFits:(DMKCoordinateRegion)region;

/**
 * @brief 设置当前地图可见范围的map rect
 * @param mapRect 要调整的map rect
 * @param animated 是否采用动画效果
 */
- (void)setVisibleMapRect:(DMKMapRect)mapRect animated:(BOOL)animated;

/**
 * @brief 设置当前地图可见范围的map rect
 * @param mapRect 要设置的map rect
 * @param insets 嵌入边界
 * @param animated 是否采用动画效果
 */
- (void)setVisibleMapRect:(DMKMapRect)mapRect edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated;

/**
 * @brief 调整map rect使其适合地图窗口显示的范围
 * @param mapRect 要调整的map rect
 * @return 调整后的maprect
 */
- (DMKMapRect)mapRectThatFits:(DMKMapRect)mapRect;

/**
 * @brief 调整map rect使其适合地图窗口显示的范围
 * @param mapRect 要调整的map rect
 * @param insets 嵌入边界
 * @return 调整后的map rect
 */
- (DMKMapRect)mapRectThatFits:(DMKMapRect)mapRect edgePadding:(UIEdgeInsets)insets;

/**
 * @brief 将经纬度坐标转化为相对于指定view的坐标
 * @param coordinate 要转化的经纬度坐标
 * @param view 指定的坐标系统的view
 * @return 指定view的坐标
 */
- (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(UIView *)view;

/**
 * @brief 将相对于view的坐标转化为经纬度坐标
 * @param point 要转化的坐标
 * @param view point所基于的view
 * @return 转化后的经纬度坐标
 */
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view;

/**
 * @brief 将map rect 转化为相对于view的坐标
 * @param region 要转化的 map rect
 * @param view 返回值所基于的view
 * @return 基于view的坐标
 */
- (CGRect)convertRegion:(DMKCoordinateRegion)region toRectToView:(UIView *)view;

/**
 * @brief 将相对于view的rectangle转化为region
 * @param rect 要转化的rectangle
 * @param view rectangle所基于的view
 * @return 转化后的region
 */
- (DMKCoordinateRegion)convertRect:(CGRect)rect toRegionFromView:(UIView *)view;

/**
 * @brief 设置追踪用户位置的模式
 * @param mode 要使用的模式
 * @param animated 是否采用动画效果
 */
- (void)setUserTrackingMode:(DMKUserTrackingMode)mode animated:(BOOL)animated;

/**
 * @brief 向地图窗口添加标注，需要实现DMKMapViewDelegate的-mapView:viewForAnnotation:函数来生成标注对应的View
 * @param annotation 要添加的标注
 */
- (void)addAnnotation:(id<DMKAnnotation>)annotation;

/**
 * @brief 移除标注
 * @param annotation 要移除的标注
 */
- (void)removeAnnotation:(id<DMKAnnotation>)annotation;

/**
 * @brief 向已添加到地图上的annotation添加infoView
 * @param annotation 目标annotation
 * @param infoView 需要添的原生view
 */
- (void)addInfoViewWithAnnotation:(id<DMKAnnotation>)annotation infoView:(UIView *)infoView;

/**
 * @brief 移除annotation上的infoView
 * @param annotation 目标annotation
 */
- (void)removeInfoViewWithAnnotation:(id<DMKAnnotation>)annotation;

/**
 * @brief 选中标注数据对应的view
 * @param annotation 标注数据
 * @param animated 是否有动画效果
 */
- (void)selectAnnotation:(id<DMKAnnotation>)annotation animated:(BOOL)animated;

/**
 * @brief 取消选中标注数据对应的view
 * @param annotation 标注数据
 * @param animated 是否有动画效果
 */
- (void)deselectAnnotation:(id<DMKAnnotation>)annotation animated:(BOOL)animated;

/**
 * @brief 向地图添加Overlay，需要实现MAMapViewDelegate的-mapView:rendererForOverlay:函数来生成标注对应的Renderer
 * @param overlay 要添加的overlay
 */
- (void)addOverlay:(id<DMKOverlay>)overlay;

/**
 * @brief 移除Overlay
 * @param overlay 要移除的overlay
 */
- (void)removeOverlay:(id<DMKOverlay>)overlay;

/**
 * @brief 获取SDK版本号
 */
- (NSString *)SDKVersion;

@end

#pragma mark - DMKMapViewDelegate

///地图view的delegate
@protocol DMKMapViewDelegate <NSObject>
@optional

/**
 * @brief 根据anntation生成对应的View
 * @param mapView 地图View
 * @param annotation 指定的标注
 * @return 生成的标注View
 */
- (DMKAnnotationView *)mapView:(DMKMapView *)mapView viewForAnnotation:(id<DMKAnnotation>)annotation;

/**
 * @brief 当mapView新添加annotation views时调用此接口
 * @param mapView 地图View
 * @param views 新添加的annotation views
 */
- (void)mapView:(DMKMapView *)mapView didAddAnnotationViews:(NSArray *)views;

/**
 * @brief 当选中一个annotation views时调用此接口
 * @param mapView 地图View
 * @param view 选中的annotationView
 */
- (void)mapView:(DMKMapView *)mapView didSelectAnnotationView:(DMKAnnotationView *)view;

/**
 * @brief 当取消选中一个annotation views时调用此接口
 * @param mapView 地图View
 * @param view 取消选中的annotationView
 */
- (void)mapView:(DMKMapView *)mapView didDeselectAnnotationView:(DMKAnnotationView *)view;

/**
 * @brief 标注view的accessory view(必须继承自UIControl)被点击时调用此接口
 * @param mapView 地图View
 * @param view callout所属的标注view
 * @param control 对应的control
 */
- (void)mapView:(DMKMapView *)mapView annotationView:(DMKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control;

/**
 * @brief 在地图View将要启动定位时调用此接口
 * @param mapView 地图View
 */
- (void)mapViewWillStartLocatingUser:(DMKMapView *)mapView;

/**
 * @brief 在地图View停止定位后调用此接口
 * @param mapView 地图View
 */
- (void)mapViewDidStopLocatingUser:(DMKMapView *)mapView;

/**
 * @brief 定位失败后调用此接口
 * @param mapView 地图View
 * @param error 错误号，参考CLError.h中定义的错误号
 */
- (void)mapView:(DMKMapView *)mapView didFailToLocateUserWithError:(NSError *)error;

/**
 * @brief 当userTrackingMode改变时调用此接口
 * @param mapView 地图View
 * @param mode 改变后的mode
 * @param animated 动画
 */
- (void)mapView:(DMKMapView *)mapView didChangeUserTrackingMode:(DMKUserTrackingMode)mode animated:(BOOL)animated;

/**
 * @brief 根据overlay生成对应的Renderer
 * @param mapView 地图View
 * @param overlay 指定的overlay
 * @return 生成的覆盖物Renderer
 */
- (DMKOverlayRenderer *)mapView:(DMKMapView *)mapView rendererForOverlay:(id<DMKOverlay>)overlay;

/**
 * @brief 地图区域即将改变时会调用此接口
 * @param mapView 地图View
 * @param animated 是否动画
 * @param bGesture 是否由手势触发
 */
- (void)mapView:(DMKMapView *)mapView regionWillChangeAnimated:(BOOL)animated gesture:(BOOL)bGesture;

/**
 * @brief 地图区域改变完成后会调用此接口
 * @param mapView 地图View
 * @param animated 是否动画
 * @param bGesture 是否由手势触发
 */
- (void)mapView:(DMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated gesture:(BOOL)bGesture;

/**
 * @brief 长按地图底图调用此接口
 * @param mapView    地图View
 * @param coordinate 长按位置经纬度
 */
- (void)mapView:(DMKMapView *)mapView didLongPressedAtCoordinate:(CLLocationCoordinate2D)coordinate;

/**
 * @brief 单击地图回调，返回经纬度
 * @param mapView 地图View
 * @param coordinate 经纬度
 */
- (void)mapView:(DMKMapView *)mapView didSingleTappedAtCoordinate:(CLLocationCoordinate2D)coordinate;

@end

NS_ASSUME_NONNULL_END
