//
//   DDMAMapView.m
//   DDMAMapKit_Private
//   Created by DDIsFriend on 2023/1/30.
    

#import "DDMAMapView.h"
#import <objc/runtime.h>
#import <DDCategoryKit_Private/UIImage+DDCategory.h>
#import <DDMAMapKit_Private/MAPointAnnotation+DDCategory.h>
#import <DDMAMapKit_Private/MABaseOverlay+DDCategory.h>
#import <DDMAMapKit_Private/DriveRouteCustomAnnotationView.h>
#import <DDMAMapKit_Private/DriveRouteCustomAnnotation.h>

@interface DDMAMapView () <MAMapViewDelegate>

@end

@implementation DDMAMapView
// MARK: <Class Initialize>
+ (void)startWithAppKey:(nullable NSString *)appKey{
    [[AMapServices sharedServices] setEnableHTTPS:YES];
    [AMapServices sharedServices].apiKey = appKey;
}

+ (void)agreePrivacy{
    [MAMapView updatePrivacyShow:AMapPrivacyShowStatusDidShow privacyInfo:AMapPrivacyInfoStatusDidContain];
    [MAMapView updatePrivacyAgree:AMapPrivacyAgreeStatusDidAgree];
}

// MARK: <Init Function>
- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (!self) return nil;
    
    [self configMapView];
    
    return self;
}

- (void)configMapView{
//    MAMapView.metalEnabled = YES;
    self.maMapView = [[MAMapView alloc] init];
    self.maMapView.delegate = self;
    [self addSubview:self.maMapView];
    
    self.maMapView.translatesAutoresizingMaskIntoConstraints = NO;
    [NSLayoutConstraint activateConstraints:@[
        [self.maMapView.leftAnchor constraintEqualToAnchor:self.leftAnchor],
        [self.maMapView.topAnchor constraintEqualToAnchor:self.topAnchor],
        [self.maMapView.rightAnchor constraintEqualToAnchor:self.rightAnchor],
        [self.maMapView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
    ]];
    
    self.maMapView.showsIndoorMap = NO;
    self.maMapView.zoomLevel = 16;
    self.maMapView.mapType = MAMapTypeStandard;
    
    self.maMapView.showsCompass = NO;
    self.maMapView.showsScale = NO;
}

- (MAOverlayRenderer *)dd_rendererForOverlay:(id <MAOverlay>)overlay{
    return [self.maMapView rendererForOverlay:overlay];
}

// MARK: <MAMapViewDelegate>
- (void)mapViewWillStartLoadingMap:(MAMapView *)mapView{
    if ([self.delegate respondsToSelector:@selector(dd_mapViewWillStartLoadingMap:)]) {
        [self.delegate dd_mapViewWillStartLoadingMap:mapView];
    }
}

- (void)mapViewDidFinishLoadingMap:(MAMapView *)mapView{
    if ([self.delegate respondsToSelector:@selector(dd_mapViewDidFinishLoadingMap:)]) {
        [self.delegate dd_mapViewDidFinishLoadingMap:mapView];
    }
}

- (void)mapViewDidFailLoadingMap:(MAMapView *)mapView withError:(NSError *)error{
    if ([self.delegate respondsToSelector:@selector(dd_mapViewDidFailLoadingMap:withError:)]) {
        [self.delegate dd_mapViewDidFailLoadingMap:mapView withError:error];
    }
}

- (void)mapView:(MAMapView *)mapView didFailLoadTerrainWithError:(NSError *)error{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:didFailLoadTerrainWithError:)]) {
        [self.delegate dd_mapView:mapView didFailLoadTerrainWithError:error];
    }
}

// MARK: <Locate>
- (void)mapViewWillStartLocatingUser:(MAMapView *)mapView{
    if ([self.delegate respondsToSelector:@selector(dd_mapViewWillStartLocatingUser:)]) {
        [self.delegate dd_mapViewWillStartLocatingUser:mapView];
    }
}

- (void)mapViewDidStopLocatingUser:(MAMapView *)mapView{
    if ([self.delegate respondsToSelector:@selector(dd_mapViewDidStopLocatingUser:)]) {
        [self.delegate dd_mapViewDidStopLocatingUser:mapView];
    }
}

- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:didUpdateUserLocation:updatingLocation:)]) {
        [self.delegate dd_mapView:mapView didUpdateUserLocation:userLocation updatingLocation:updatingLocation];
    }
}

- (void)mapViewRequireLocationAuth:(CLLocationManager *)locationManager {
    if ([self.delegate respondsToSelector:@selector(dd_mapViewRequireLocationAuth:)]) {
        [self.delegate dd_mapViewRequireLocationAuth:locationManager];
    }
}

- (void)mapView:(MAMapView *)mapView didFailToLocateUserWithError:(NSError *)error{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:didFailToLocateUserWithError:)]) {
        [self.delegate dd_mapView:mapView didFailToLocateUserWithError:error];
    }
}

- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:viewForAnnotation:)]) {
        return [self.delegate dd_mapView:mapView viewForAnnotation:annotation];
    }
    
    if ([annotation isMemberOfClass:[MAPointAnnotation class]]){
        MAPointAnnotation *pointAnnotation = (MAPointAnnotation *)annotation;
        static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
        MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.annotation = pointAnnotation;
        annotationView.image = pointAnnotation.dd_image;
        if (pointAnnotation.customCalloutView != nil) {
            annotationView.customCalloutView = [[MACustomCalloutView alloc] initWithCustomView:pointAnnotation.customCalloutView];
            annotationView.canShowCallout = YES;
            annotationView.selected = YES;
        }
        return annotationView;
    }

    if ([annotation isMemberOfClass:[MAAnimatedAnnotation class]]) {
        MAAnimatedAnnotation *animatedAnnotation = (MAAnimatedAnnotation *)annotation;
        static NSString *pointReuseIndentifier = @"AnimatedAnnotationPointReuseIndentifier";
        MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.annotation = animatedAnnotation;
        annotationView.image = animatedAnnotation.dd_image;
        return annotationView;
    }
    
    if ([annotation isMemberOfClass:[DriveRouteCustomAnnotation class]]){
        DriveRouteCustomAnnotation *pointAnnotation = (DriveRouteCustomAnnotation *)annotation;
        static NSString *pointReuseIndentifier = @"DriveRouteCustomAnnotationPointReuseIndentifier";
        DriveRouteCustomAnnotationView *annotationView = (DriveRouteCustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil)
        {
            annotationView = [[DriveRouteCustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.annotation = pointAnnotation;
        annotationView.image = pointAnnotation.dd_image;
        annotationView.customTextLabel.attributedText = pointAnnotation.customAttributedText;
        return annotationView;
    }
    
    return nil;
}

- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id <MAOverlay>)overlay{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:rendererForOverlay:)]) {
       return [self.delegate dd_mapView:mapView rendererForOverlay:overlay];
    }
    
    if ([overlay isMemberOfClass:[MAPolyline class]]){
        MAPolyline *polyline = (MAPolyline *)overlay;
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:polyline];
        polylineRenderer.lineWidth    = polyline.dd_lineWidth;
        polylineRenderer.strokeColor  = polyline.dd_strokeColor;
        polylineRenderer.lineJoinType = polyline.dd_lineJoinType;
        polylineRenderer.lineCapType  = polyline.dd_lineCapType;
        return polylineRenderer;
    }
    
    if ([overlay isMemberOfClass:[MATraceReplayOverlay class]]) {
        MATraceReplayOverlay *traceReplayOverlay = (MATraceReplayOverlay *)overlay;
        MATraceReplayOverlayRenderer *traceReplayOverlayRenderer = [[MATraceReplayOverlayRenderer alloc] initWithOverlay:traceReplayOverlay];
        traceReplayOverlayRenderer.lineWidth = traceReplayOverlay.dd_lineWidth;
        traceReplayOverlayRenderer.strokeColors = traceReplayOverlay.dd_strokeColors;
        traceReplayOverlayRenderer.lineJoinType = traceReplayOverlay.dd_lineJoinType;
        traceReplayOverlayRenderer.lineCapType = traceReplayOverlay.dd_lineCapType;
        self.traceReplayOverlay = traceReplayOverlay;
        self.traceReplayOverlayRenderer = traceReplayOverlayRenderer;
        return traceReplayOverlayRenderer;
    }
    
    return nil;
}

- (void)mapView:(MAMapView *)mapView didAnnotationViewTapped:(MAAnnotationView *)view{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:didAnnotationViewTapped:)]) {
        [self.delegate dd_mapView:mapView didAnnotationViewTapped:view];
    }
}

- (void)mapView:(MAMapView *)mapView didAddOverlayRenderers:(NSArray *)overlayRenderers{
    if ([self.delegate respondsToSelector:@selector(dd_mapView:didAddOverlayRenderers:)]) {
        [self.delegate dd_mapView:mapView didAddOverlayRenderers:overlayRenderers];
    }
}
@end

@implementation DDMAMapView (Location)
- (MAUserLocation *)maUserLocation{
    return self.maMapView.userLocation;
}

- (void)updateLocationViewWithParam:(MAUserLocationRepresentation *)representation{
    [self.maMapView updateUserLocationRepresentation:representation];
}
@end

@implementation DDMAMapView (Trace)
- (void)setTraceReplayOverlay:(MATraceReplayOverlay *)traceReplayOverlay{
    objc_setAssociatedObject(self, @selector(traceReplayOverlay), traceReplayOverlay, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MATraceReplayOverlay *)traceReplayOverlay{
    return objc_getAssociatedObject(self, _cmd);
}

- (void)setTraceReplayOverlayRenderer:(MATraceReplayOverlayRenderer *)traceReplayOverlayRenderer{
    objc_setAssociatedObject(self, @selector(traceReplayOverlayRenderer), traceReplayOverlayRenderer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MATraceReplayOverlayRenderer *)traceReplayOverlayRenderer{
    return objc_getAssociatedObject(self, _cmd);
}
@end
