import Foundation
import UIKit
import CoreLocation
import BaiduMapAPI_Map
import ObjectiveC

extension MapViewImpl {
    private func updateRegionSnapshot(_ mapView: BMKMapView) {
        let center = mapView.centerCoordinate
        self.centerLatitude = center.latitude
        self.centerLongitude = center.longitude
        self.zoomLevelValue = Double(mapView.zoomLevel)
        NSLog("regionchange latitude=\(center.latitude), longitude=\(center.longitude), scale=\(Double(mapView.zoomLevel))")
    }
    
    public func mapViewDidFinishLoading(_ mapView: BMKMapView!) {
        self.updateRegionSnapshot(mapView)
        self.isMapLoaded = true
    }
    
    public func mapViewDidRenderValidData(_ mapView: BMKMapView!, withError error: Error!) {
        self.updateRegionSnapshot(mapView)
    }
    
    public func mapViewDidFinishRendering(_ mapView: BMKMapView!) {
        self.updateRegionSnapshot(mapView)
        self.renderReady = true
    }
    
    public func mapStatusDidChanged(_ mapView: BMKMapView!) {
        self.updateRegionSnapshot(mapView)
        self.regionChanging = true
    }
    
    public func mapView(_ mapView: BMKMapView!, regionWillChangeAnimated animated: Bool, reason reason: BMKRegionChangeReason) {
        self.changeReason = reason.rawValue
        self.updateRegionSnapshot(mapView)
        self.regionChangedStart = true
    }
    
    public func mapView(_ mapView: BMKMapView!, regionDidChangeAnimated animated: Bool, reason reason: BMKRegionChangeReason) {
        self.updateRegionSnapshot(mapView)
        self.regionChangedFinish = true
    }
    
    public func mapView(_ mapView: BMKMapView!, onClickedMapBlank coordinate: CLLocationCoordinate2D) {
        self.tappedLatitude = coordinate.latitude
        self.tappedLongitude = coordinate.longitude
        self.mapTapped = true
    }
    
    public func mapView(_ mapView: BMKMapView!, onClickedMapPoi mapPoi: BMKMapPoi!) {
        self.tappedPoiName = mapPoi.text ?? ""
        self.tappedPoiUid = mapPoi.uid ?? ""
        self.tappedPoiLatitude = mapPoi.pt.latitude
        self.tappedPoiLongitude = mapPoi.pt.longitude
        self.poiTapped = true
    }
    
    public func mapview(_ mapView: BMKMapView!, onLongClick coordinate: CLLocationCoordinate2D) {
        self.longPressedLatitude = coordinate.latitude
        self.longPressedLongitude = coordinate.longitude
        self.longPressed = true
    }
    
    public func mapview(_ mapView: BMKMapView!, onDoubleClick coordinate: CLLocationCoordinate2D) {
        self.doublePressedLatitude = coordinate.latitude
        self.doublePressedLongitude = coordinate.longitude
        self.doublePressed = true
    }
    
    public func mapView(_ mapView: BMKMapView!, onClickedBMKOverlayView overlayView: BMKOverlayView!) {
        guard let overlayView = overlayView else {
            return
        }
        
        // Marker (icon click)
        if let iconMarkerView = overlayView as? BMKIconMarkerView,
           let marker = iconMarkerView.overlay as? BMKIconMarker {
            for (overlayId, storedMarker) in self.markerOverlays {
                if storedMarker === marker {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "marker"
                    self.tappedIsRichView = false
                    self.tappedRichViewItemIndex = -1
                    self.overlayTapped = true
                    break
                }
            }
            return
        }
        
        // RichView background click (non-clickable area)
        if let marker = overlayView.overlay as? BMKIconMarker {
            for (overlayId, storedMarker) in self.markerOverlays {
                if storedMarker === marker {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "marker"
                    self.tappedIsRichView = true
                    self.tappedRichViewItemIndex = -1
                    self.overlayTapped = true
                    break
                }
            }
            return
        }
        if !(overlayView is BMKTextMarkerView), let textMarker = overlayView.overlay as? BMKTextMarker {
            for (overlayId, storedLabel) in self.labelOverlays {
                if storedLabel === textMarker {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "label"
                    self.tappedIsRichView = true
                    self.tappedRichViewItemIndex = -1
                    self.overlayTapped = true
                    break
                }
            }
            return
        }
        
        // Circle
        if let circleView = overlayView as? BMKCircleView,
           let circle = circleView.overlay as? BMKCircle {
            for (overlayId, storedCircle) in self.circleOverlays {
                if storedCircle === circle {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "circle"
                    self.overlayTapped = true
                    NSLog("点击Circle, overlayId=%d", overlayId)
                    break
                }
            }
            return
        }
        
        // Polyline
        if let polylineView = overlayView as? BMKPolylineView,
           let polyline = polylineView.overlay as? BMKPolyline {
            for (overlayId, storedPolyline) in self.polylineOverlays {
                if storedPolyline === polyline {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "polyline"
                    self.overlayTapped = true
                    NSLog("点击Polyline, overlayId=%d", overlayId)
                    break
                }
            }
            return
        }
        
        // Polygon
        if let polygonView = overlayView as? BMKPolygonView,
           let polygon = polygonView.overlay as? BMKPolygon {
            for (overlayId, storedPolygon) in self.polygonOverlays {
                if storedPolygon === polygon {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "polygon"
                    self.overlayTapped = true
                    NSLog("点击Polygon, overlayId=%d", overlayId)
                    break
                }
            }
            return
        }
        
        // Label (BMKTextMarker)
        if let textMarkerView = overlayView as? BMKTextMarkerView,
           let textMarker = textMarkerView.overlay as? BMKTextMarker {
            for (overlayId, storedLabel) in self.labelOverlays {
                if storedLabel === textMarker {
                    self.tappedOverlayId = overlayId
                    self.tappedOverlayType = "label"
                    self.tappedIsRichView = false
                    self.tappedRichViewItemIndex = -1
                    self.overlayTapped = true
                    NSLog("点击Label, overlayId=%d", overlayId)
                    break
                }
            }
            return
        }
    }
    
    public func mapView(_ mapView: BMKMapView!, viewFor overlay: BMKOverlay!) -> BMKOverlayView! {
        if let marker = overlay as? BMKIconMarker {
            let view = BMKIconMarkerView(overlay: marker)
            if let markerView = view {
                markerView.isClickable = true
                self.applyMarkerStyle(marker, markerView)
                return markerView
            }
            return nil
        }
        
        if let textMarker = overlay as? BMKTextMarker {
            let view = BMKTextMarkerView(overlay: textMarker)
            if let textMarkerView = view {
                textMarkerView.isClickable = true
                return textMarkerView
            }
            return nil
        }
        
        if let circle = overlay as? BMKCircle {
            let view = BMKCircleView(overlay: circle)
            if let circleView = view {
                let strokeColor = (objc_getAssociatedObject(circle, UnsafeRawPointer(bitPattern: 3001)!) as? String) ?? "#0A84FF"
                let fillColor = (objc_getAssociatedObject(circle, UnsafeRawPointer(bitPattern: 3002)!) as? String) ?? "rgba(10,132,255,0.2)"
                let strokeWidth = (objc_getAssociatedObject(circle, UnsafeRawPointer(bitPattern: 3003)!) as? NSNumber)?.doubleValue ?? 2

                circleView.strokeColor = self.colorFromString(strokeColor, UIColor.systemBlue)
                circleView.fillColor = self.colorFromString(fillColor, UIColor.systemBlue.withAlphaComponent(0.2))
                circleView.lineWidth = CGFloat(strokeWidth)
                circleView.isClickable = true

                return circleView
            }
            return nil
        }

        if let polyline = overlay as? BMKPolyline {
            let view = BMKPolylineView(overlay: polyline)
            if let polylineView = view {
                self.applyPolylineStyle(polyline, polylineView)
                return polylineView
            }
            return nil
        }
        if let polygon = overlay as? BMKPolygon {
            let view = BMKPolygonView(overlay: polygon)
            if let polygonView = view {
                let strokeColor = (objc_getAssociatedObject(polygon, UnsafeRawPointer(bitPattern: 2001)!) as? String) ?? "#0A84FF"
                let fillColor = (objc_getAssociatedObject(polygon, UnsafeRawPointer(bitPattern: 2002)!) as? String) ?? "rgba(10,132,255,0.2)"
                let strokeWidth = (objc_getAssociatedObject(polygon, UnsafeRawPointer(bitPattern: 2003)!) as? NSNumber)?.doubleValue ?? 2
                
                polygonView.strokeColor = self.colorFromString(strokeColor, UIColor.systemBlue)
                polygonView.fillColor = self.colorFromString(fillColor, UIColor.systemBlue.withAlphaComponent(0.2))
                polygonView.lineWidth = CGFloat(strokeWidth)
                polygonView.isClickable = true
                return polygonView
            }
            
            return nil
        }
        if let multiPoint = overlay as? BMKMultiPointOverlay {
            let view = BMKMultiPointOverlayView(multiPointOverlay: multiPoint)
            if let multiPointView = view {
                if let iconPath = objc_getAssociatedObject(multiPoint, UnsafeRawPointer(bitPattern: 5001)!) as? String {
                    if let icon = UIImage(contentsOfFile: iconPath) {
                        multiPointView.icon = icon
                    }
                }
                if let width = objc_getAssociatedObject(multiPoint, UnsafeRawPointer(bitPattern: 5002)!) as? NSNumber,
                   let height = objc_getAssociatedObject(multiPoint, UnsafeRawPointer(bitPattern: 5003)!) as? NSNumber {
                    multiPointView.pointSize = CGSize(width: width.intValue, height: height.intValue)
                }
                if let anchorX = objc_getAssociatedObject(multiPoint, UnsafeRawPointer(bitPattern: 5004)!) as? NSNumber,
                   let anchorY = objc_getAssociatedObject(multiPoint, UnsafeRawPointer(bitPattern: 5005)!) as? NSNumber {
                    multiPointView.anchor = CGPoint(x: anchorX.doubleValue, y: anchorY.doubleValue)
                }
                multiPointView.isClickable = true
                multiPointView.delegate = self
                return multiPointView
            }
            return nil
        }
        return nil
    }
}

extension MapViewImpl: BMKMultiPointOverlayViewDelegate {
    public func multiPointOverlayView(_ multiPointOverlayView: BMKMultiPointOverlayView!, didItemTapped item: BMKMultiPointItem!) {
        guard let item = item else { return }
        for (overlayId, storedOverlay) in self.multiPointOverlays {
            if let overlay = multiPointOverlayView.overlay as? BMKMultiPointOverlay, overlay === storedOverlay {
                self.tappedMultiPointOverlayId = overlayId
                if let items = overlay.items as? [BMKMultiPointItem] {
                    self.tappedMultiPointIndex = items.firstIndex(where: { $0 === item }) ?? -1
                } else {
                    self.tappedMultiPointIndex = -1
                }
                self.tappedMultiPointLat = item.coordinate.latitude
                self.tappedMultiPointLng = item.coordinate.longitude
                self.tappedMultiPointTitle = item.title ?? ""
                self.multiPointTapped = true
                break
            }
        }
    }
}
