//
//  MapViewController.swift
//  Runner
//
//  Created by Groot on 2025/5/7.
//

import UIKit
import MapKit
import Combine

class MapViewController: UIViewController {
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    let viewModel: MapViewModel
    let mapView = MKMapView()
    private var cancellables = Set<AnyCancellable>()
    
    init(viewModel: MapViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
        mapView.showsUserLocation = false
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
        setupMap()
        bindViewModel()
    }

    private func setupView() {
        mapView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(mapView)
        NSLayoutConstraint.activate([
            mapView.topAnchor.constraint(equalTo: view.topAnchor),
            mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
    }

    private func setupMap() {
        mapView.delegate = self
        mapView.showsUserLocation = false
        mapView.mapType = .mutedStandard
    }
    
    private func bindViewModel() {
        viewModel.$currentRegion
            .compactMap { $0 }
            .receive(on: DispatchQueue.main)
            .sink { [weak self] region in
                self?.mapView.setRegion(region, animated: true)
            }
            .store(in: &cancellables)

        viewModel.$markers
            .receive(on: DispatchQueue.main)
            .sink { [weak self] markers in
                self?.mapView.removeAnnotations(self?.mapView.annotations ?? [])
                UIView.animate(withDuration: 0.3) {
                    self?.mapView.addAnnotations(markers)
                }
            }
            .store(in: &cancellables)

        viewModel.$polylines
            .receive(on: DispatchQueue.main)
            .sink { [weak self] polylines in
                self?.mapView.removeOverlays(self?.mapView.overlays ?? [])
                self?.mapView.addOverlays(polylines.map({ $0.polyline }))

                if let padding = polylines.last?.mapPadding {
                    self?.mapView.fitsAllPoints(
                        points: polylines.last?.points.compactMap({ MKMapPoint($0) }) ?? [],
                        padding: padding.padding,
                        animated: true
                    )
                }
            }
            .store(in: &cancellables)
        
        //移动至多个点的位置，并提供设置padding距离
        viewModel.$suitableLocation
            .receive(on: DispatchQueue.main)
            .sink{ [weak self] polylines in
                if let padding = polylines.last?.mapPadding {
                    if let atMapPoint : [CLLocationCoordinate2D] = polylines.last?.points {
                        self?.mapView.moveToSuitableLocation(points: atMapPoint, padding: padding)
                    }
                }
            }
            .store(in: &cancellables)
    }
}

extension MapViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard let marker = annotation as? ATMapMarker else {
            return nil
        }
        
        let annotationView = (mapView.dequeueReusableAnnotationView(withIdentifier: MapAnnotationView.identifier) as? MapAnnotationView) ?? MapAnnotationView(annotation: marker, reuseIdentifier: MapAnnotationView.identifier)
        annotationView.marker = marker
        annotationView.prepareForDisplay()
        return annotationView
    }

    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        guard var marker = view.annotation as? ATMapMarker else {
            return
        }
        
        viewModel.handleMarkerTap(marker: &marker)
    }

    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        let renderer = MKPolylineRenderer(overlay: overlay)
        renderer.lineWidth = 6
        //rgba(123, 125, 255, 1)
        renderer.strokeColor = UIColor(red: 123 / 255, green: 125 / 255, blue: 255 / 255, alpha: 1)
        renderer.lineCap = .round
        renderer.lineJoin = .round
        return renderer
    }
} 
