//
//  MapRepresentable.swift
//  forShip
//
//  Created by Mamoru Sugita on 2023/10/18.
//

import Foundation
import SwiftUI
import MapboxMaps
import UIKit

struct MapRepresentable: UIViewControllerRepresentable{
    @ObservedObject var sharingData = SharingData.shared
    
    @State var mapVC = MapViewController()
    func makeUIViewController(context: Context) -> some UIViewController {
        mapVC
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        if let ecaArea = sharingData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first{
            mapVC.updateEcaLine(line: ecaArea.points)
        }
    }
}

class MapViewController : UIViewController{
    
    internal var mapView: MapView!
    
    var ownShipSymbol = MapSource(layer: .OwnShip)
    var ecaLine = MapSource(layer: .EcaLine)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96)
        let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate,
                                                                  zoom: 2))

        mapView = MapView(frame: view.bounds, mapInitOptions: options)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        
        self.view.addSubview(mapView)

        
        mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in
            self.addLayers()
            
        }
        
    }
    
    func addLayers(){
        
        try! mapView.mapboxMap.style.addImage(UIImage(named: "account")!, id: IconImage.OwnShip.rawValue)

        let point = Point(LocationCoordinate2D(latitude: 0, longitude: 0))
        var feature = Feature(geometry: point)
//        feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.OwnShip.rawValue)]
        ownShipSymbol.source.data = .feature(feature)
        var ownShipSymbolLayer = SymbolLayer(id: ownShipSymbol.layerId)
        ownShipSymbolLayer.source = ownShipSymbol.sourceId
        ownShipSymbolLayer.iconImage = .expression(Exp(.get) {
            PropertyKey.IconImage.rawValue
        })
        ownShipSymbolLayer.iconRotationAlignment = .constant(.map)
        ownShipSymbolLayer.iconAllowOverlap = .constant(true)
        ownShipSymbolLayer.iconIgnorePlacement = .constant(true)
        ownShipSymbolLayer.iconRotate = .expression(Exp(.get) {
            PropertyKey.Bearing.rawValue
        })

        try! mapView.mapboxMap.style.addSource(ownShipSymbol.source, id: ownShipSymbol.sourceId)
        try? mapView.mapboxMap.style.addLayer(ownShipSymbolLayer)
        
        
        let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
        var ecaLinefeature = Feature(geometry: ecaLineString)
        ecaLine.source.data = .feature(ecaLinefeature)
        var ecaLineLayer = LineLayer(id: ecaLine.layerId)
        ecaLineLayer.source = ecaLine.sourceId
        ecaLineLayer.lineColor = .expression(Exp(.get) {
            PropertyKey.Color.rawValue
        })
        ecaLineLayer.lineDasharray = .constant([2,1])

        try! mapView.mapboxMap.style.addSource(ecaLine.source, id: ecaLine.sourceId)
        try? mapView.mapboxMap.style.addLayer(ecaLineLayer)
    }
    
    func updateOwnShip(location: CLLocationCoordinate2D){
        var geoJSON = Feature(geometry: Point(location))
        geoJSON.properties = [PropertyKey.Bearing.rawValue: .number(90),
                              PropertyKey.IconImage.rawValue: .string(IconImage.OwnShip.rawValue)]
        try! self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.ownShipSymbol.sourceId,
                                                              geoJSON: .feature(geoJSON))
    }
    
    
    func updateEcaLine(line: [CLLocationCoordinate2D]){
        do{
            var geoJson = Feature(geometry: LineString(line))
            geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
            
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson))
        }catch{
            
        }
    }

    
    
    
    enum PropertyKey : String {
        case IconImage
        case Bearing
        case Color
    }
    
    enum IconImage: String, CaseIterable{
        case OwnShip
    }
}

