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

import Foundation
import SwiftUI
import MapboxMaps
import UIKit

struct MapRepresentable: UIViewControllerRepresentable {
    @ObservedObject var ecaData = SharingData.eca
    @ObservedObject var ngaData = SharingData.nga
    @ObservedObject var location = SharingData.location
    @ObservedObject var map = SharingData.map
    @ObservedObject var pushHistory = SharingData.pushHistory

    @State var mapVC = MapViewController()
    //作成したいViewControllerを返すメソッド
    func makeUIViewController(context: Context) -> some UIViewController {
        mapVC
    }

    //Viewが更新された場合に必要な処理を実装
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        let ecaArea = ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first
        if let ecaArea = ecaArea {
            mapVC.updateEcaLine(line: ecaArea.points)
        } else {
            mapVC.removeEcaLine()
        }
        
        //ECA領域を画面中央に表示
        if let focusEcaAreaId = ecaData.focusEca, let focusEca = ecaData.ecaArea[focusEcaAreaId] {
            mapVC.updateCamera(location: focusEca.centerPosition, zoomlevel: focusEca.zoomLevel)
            mapVC.updateOneTimeEca(eca: focusEca.points)
            //10秒後削除
            DispatchQueue.main.asyncAfter(deadline: .now() + 15.0) {
                mapVC.updateOneTimeEca(eca: nil)
            }
        }
        
        //NGA領域を画面中央に表示
        if let AreaId = ngaData.focusNga, let uuid = NSUUID(uuidString: AreaId) {
            if let focusNga = ngaData.ngaArea[uuid as UUID] {
                if focusNga.points.count > 0 {
                    let centerPos = LocationCalculation.CenterPoint2(positions: focusNga.points)
                    mapVC.updateCamera(location: centerPos, zoomlevel: 10.0)
                }
            }
        }

        //通知場所を画面中央に表示
        if let focusPushHistoryId = pushHistory.focusPushHistory, let focusPushHistory = pushHistory.pushHistoryData[focusPushHistoryId] {
            if let position = focusPushHistory.position {
                if let latitude = position.lat, let longitude = position.lon {
                    mapVC.updateCamera(location: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoomlevel: nil)
                }
            }
        }
        
        //自船を画面中央に表示
        if location.focusOwnShip {
            mapVC.updateCamera(location: location.location, zoomlevel: nil)
        }
        
        if let mylocation = location.location {
            mapVC.updateOwnShipSymbol(location: mylocation, bearing: location.heading)
            
            if let ecaArea = ecaArea {
                mapVC.updateEcaSwitchingLine(center: mylocation, notice: ecaArea.swNotice, start: ecaArea.swStart, finish: ecaArea.swFinish)
            } else {
                mapVC.removeEcaSwitchingLine()
            }
        }
        mapVC.updateWakeLines(legLine: map.legLine, portLine: map.portLine, starboardLine: map.starboardLine)
        mapVC.updateWayPoints(points: map.wayPoints)
        
        mapVC.updateEditTarget()
        
        if SharingData.nga.editType == EditNgaType.addPoint || SharingData.nga.editType == EditNgaType.movePoint {
            mapVC.updateEditArea(remove: false)
        }

        if SharingData.nga.editType == EditNgaType.registered {
            mapVC.updateEditArea(remove: true)
            SharingData.nga.editType = EditNgaType.nonEdit
        }
        
        if SharingData.nga.editType == EditNgaType.deletePoint {
            mapVC.updateEditArea(remove: true)
            mapVC.deleteSymbol()
            mapVC.updateEditArea(remove: false)
        }
        
        if SharingData.map.isMapFree == true {
            mapVC.lockEditPoint(isLocked: true)
            SharingData.map.isMapFree = false
        }

        mapVC.updateAlertArea()
    }
}

class MapViewController : UIViewController {
    internal var mapView: MapView!
    internal var touchedFeatures: Feature? = nil

    override func viewDidLoad() {
        super.viewDidLoad()
        let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96)
        //        let url = StyleURI(rawValue: "mapbox://styles/jmarinecloud/cltrwnk5i01j901ra3g4n7dtz")K
        //        let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2), styleURI: url)
        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.addIconImage()
            self.addLayers()
        }

        //地図上クリック
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:)))
        singleTap.numberOfTapsRequired = 1
        singleTap.numberOfTouchesRequired = 1
        //下記処理を加えると動作しない
        //        for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
        //            singleTap.require(toFail: recognizer)
        //        }
        mapView.addGestureRecognizer(singleTap)

        //地図上長押し
        let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMapLongPress(sender:)))
        for recognizer in mapView.gestureRecognizers! where recognizer is UILongPressGestureRecognizer {
            longPress.require(toFail: recognizer)
        }
        mapView.addGestureRecognizer(longPress)
    }

    /**
     * 地図上クリックアクション
     */
    @objc func handleMapTap(sender: UITapGestureRecognizer) {
        let spot = sender.location(in: mapView)
        let coordinate = mapView.mapboxMap.coordinate(for: spot)
        mapClick(point: spot, coordinate: coordinate)
    }

    /**
     * 地図上長押しアクション
     */
    @objc func handleMapLongPress(sender: UILongPressGestureRecognizer ) {
        let spot = sender.location(in: mapView)
        let coordinate = mapView.mapboxMap.coordinate(for: spot)
        mapLongClick(point: spot, coordinate: coordinate)
    }

    /**
     * 地図上ドラッグアクション
     */
    @objc func handleMapDrug(sender: UIPanGestureRecognizer) {
        let spot = sender.location(in: mapView)
        let coordinate = mapView.mapboxMap.coordinate(for: spot)
        mapDrug(point: spot, coordinate: coordinate)

        if SharingData.nga.editType == EditNgaType.movePoint {
            if let nga = SharingData.nga.editNga, let no = SharingData.nga.selectPoint {
                var ngaData = nga
                ngaData.points[no] = coordinate
                SharingData.nga.targetLocation = coordinate
                SharingData.nga.editNga = ngaData
                updateEditArea()
            }
        }
    }

    /**
     * アイコンの状態表記
     */
    let IconImageList = [
        IconImageData(name: "ownShip_normal", id: IconImage.OwnShip_Normal.rawValue),
        IconImageData(name: "ownShip_alarm", id: IconImage.OwnShip_Alarm.rawValue),
        IconImageData(name: "ownShip_caution", id: IconImage.OwnShip_Caution.rawValue),
        IconImageData(name: "ownShip_emergency", id: IconImage.OwnShip_Emergency.rawValue),
        IconImageData(name: "ownShip_necstemergency", id: IconImage.OwnShip_NeCST_Emergency.rawValue),
        IconImageData(name: "ownShip_offline", id: IconImage.OwnShip_Offline.rawValue),
        IconImageData(name: "ownShip_unknown", id: IconImage.OwnShip_Unknown.rawValue),
        IconImageData(name: "ownShip_warning", id: IconImage.OwnShip_Warning.rawValue),
        IconImageData(name: "swNoticeBack", id: IconImage.SwNoticeBack.rawValue),
        IconImageData(name: "swStartBack", id: IconImage.SwStartBack.rawValue),
        IconImageData(name: "swFinishBack", id: IconImage.SwFinisheBack.rawValue),
        IconImageData(name: "areaPoint", id: IconImage.AreaPoint.rawValue),
        IconImageData(name: "target", id: IconImage.Target.rawValue),
        IconImageData(name: "addSymbol", id: IconImage.AddSymbol.rawValue)
    ]

    enum IconImage: String, CaseIterable {
        case OwnShip_Alarm
        case OwnShip_Caution
        case OwnShip_Emergency
        case OwnShip_NeCST_Emergency
        case OwnShip_Normal
        case OwnShip_Offline
        case OwnShip_Unknown
        case OwnShip_Warning
        case SwNoticeBack
        case SwStartBack
        case SwFinisheBack
        case AreaPoint
        case Target
        case AddSymbol
    }

    struct IconImageData {
        var name: String
        var id: String
    }

    func addIconImage() {
        do{
            for iconData in IconImageList {
                if let iconImage = UIImage(named: iconData.name) {
                    try mapView.mapboxMap.style.addImage(iconImage, id: iconData.id)
                }
            }
        } catch {
            print(debug: "called")
        }
    }

    /**
     * レイヤー処理
     */
    enum LayerEnum: String {
        case OwnShipSymbol
        case EcaLine
        case SwitchingLine
        case SwLineLabel
        case WayPoints
        case WakeLines
        case OneTimeEca
        case EditTargetSymbol
        case EditAreaAddSymbol
        case EditAreaSymbol
        case EditAreaLine
        case EditAreaFill
        case AlertAreaLabel
        case AlertAreaSymbol
        case AlertAreaLine
        case AlertAreaFill
    }

    var ownShipSymbol = MapSource(layer: .OwnShipSymbol)
    var ecaLine = MapSource(layer: .EcaLine)
    var ecaSwitchingLine = MapSource(layer: .SwitchingLine)
    var ecaSwLineLabel = MapSource(layer: .SwLineLabel)
    var wayPoints = MapSource(layer: .WayPoints)
    var wakeLines = MapSource(layer: .WakeLines)
    var oneTimeEca = MapSource(layer: .OneTimeEca)
    var editTargetSymbol = MapSource(layer: .EditTargetSymbol)
    var editAreaAddSymbol = MapSource(layer: .EditAreaAddSymbol)
    var editAreaFill = MapSource(layer: .EditAreaFill)
    var editAreaLine = MapSource(layer: .EditAreaLine)
    var editAreaSymbol = MapSource(layer: .EditAreaSymbol)
    var alertAreaLabel = MapSource(layer: .AlertAreaLabel)
    var alertAreaFill = MapSource(layer: .AlertAreaFill)
    var alertAreaLine = MapSource(layer: .AlertAreaLine)
    var alertAreaSymbol = MapSource(layer: .AlertAreaSymbol)

    /**
     * レイヤー作成
     */
    func addLayers() {
        alertAreaFillLayer()
        alertAreaLineLayer()
        editAreaFillLayer()
        editAreaLineLayer()
        editAreaAddSymbolLayer()
        editAreaSymbolLayer()
        editTargetSymbolLayer()
        wayPointsLayer()
        wakeLineLayer()         //航路ライン
        ecaSwitchingLineLabelLayer()
        ecaSwitchingLineLayer()
        oneTimeEcaLineLayer()
        ecaLineLayer()          //ECAライン
        ownShipSymbolLayer()    //自船シンボル
    }

    /**
     * 自船シンボル表示レイヤー
     */
    private func ownShipSymbolLayer() {
        let point = Point(LocationCoordinate2D(latitude: 0, longitude: 0))
        ownShipSymbol.source.data = .feature(Feature(geometry: point))
        try! mapView.mapboxMap.style.addSource(ownShipSymbol.source, id: ownShipSymbol.sourceId)

        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.addLayer(ownShipSymbolLayer)
    }

    /**
     * ECAライン表示レイヤー
     */
    private func ecaLineLayer() {
        let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
        let ecaLinefeature = Feature(geometry: ecaLineString)
        ecaLine.source.data = .feature(ecaLinefeature)
        try! mapView.mapboxMap.style.addSource(ecaLine.source, id: ecaLine.sourceId)

        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.addLayer(ecaLineLayer)
    }

    /**
     * ECAライン一時表示レイヤー
     */
    private func oneTimeEcaLineLayer() {
        let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
        let oneTimeEcaLinefeature = Feature(geometry: ecaLineString)
        oneTimeEca.source.data = .feature(oneTimeEcaLinefeature)
        try! mapView.mapboxMap.style.addSource(oneTimeEca.source, id: oneTimeEca.sourceId)

        var oneTimeEcaLayer = LineLayer(id: oneTimeEca.layerId)
        oneTimeEcaLayer.source = oneTimeEca.sourceId
        oneTimeEcaLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        oneTimeEcaLayer.lineDasharray = .constant([2,1])
        try? mapView.mapboxMap.style.addLayer(oneTimeEcaLayer)
    }

    /**
     * ECA切替ライン表示レイヤー
     */
    private func ecaSwitchingLineLayer() {
        ecaSwitchingLine.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(ecaSwitchingLine.source, id: ecaSwitchingLine.sourceId)

        var ecaSwitchingLineLayer = LineLayer(id: ecaSwitchingLine.layerId)
        ecaSwitchingLineLayer.source = ecaSwitchingLine.sourceId
        ecaSwitchingLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        ecaSwitchingLineLayer.lineDasharray = .constant([2,1])
        try? mapView.mapboxMap.style.addLayer(ecaSwitchingLineLayer)
    }

    /**
     * ECA切替ラインラベル表示レイヤー
     */
    private func ecaSwitchingLineLabelLayer() {
        ecaSwLineLabel.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(ecaSwLineLabel.source, id: ecaSwLineLabel.sourceId)

        var ecaSwLabelLayer = SymbolLayer(id: ecaSwLineLabel.layerId)
        ecaSwLabelLayer.source = ecaSwLineLabel.sourceId
        ecaSwLabelLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
        ecaSwLabelLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
        ecaSwLabelLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        ecaSwLabelLayer.iconTextFit = .constant(.both)
        ecaSwLabelLayer.iconTextFitPadding = .constant([0,6,0,6])
        try? mapView.mapboxMap.style.addLayer(ecaSwLabelLayer)
    }

    /**
     * 航跡ラインレイヤー
     */
    private func wakeLineLayer() {
        wakeLines.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(wakeLines.source, id: wakeLines.sourceId)

        var wakeLineLayer = LineLayer(id: wakeLines.layerId)
        wakeLineLayer.source = wakeLines.sourceId
        wakeLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        try? mapView.mapboxMap.style.addLayer(wakeLineLayer)
    }

    /**
     * wayポイントレイヤー
     */
    private func wayPointsLayer() {
        wayPoints.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(wayPoints.source, id: wayPoints.sourceId)

        var wayPointsLayer = SymbolLayer(id: wayPoints.layerId)
        wayPointsLayer.source = wayPoints.sourceId
        wayPointsLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
        wayPointsLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        try? mapView.mapboxMap.style.addLayer(wayPointsLayer)
    }

    /**
     * NGA Editターゲットレイヤー
     */
    private func editTargetSymbolLayer() {
        editTargetSymbol.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(editTargetSymbol.source, id: editTargetSymbol.sourceId)

        var editTargetSymbolLayer = SymbolLayer(id: editTargetSymbol.layerId)
        editTargetSymbolLayer.source = editTargetSymbol.sourceId
        editTargetSymbolLayer.iconSize = .expression(Exp(.get) {PropertyKey.Size.rawValue})
        editTargetSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
        editTargetSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        try? mapView.mapboxMap.style.addLayer(editTargetSymbolLayer)
    }

    /**
     * NGA Edit追加シンボルレイヤー
     */
    private func editAreaAddSymbolLayer() {
        editAreaAddSymbol.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(editAreaAddSymbol.source, id: editAreaAddSymbol.sourceId)

        var editAreaAddSymbolLayer = SymbolLayer(id: editAreaAddSymbol.layerId)
        editAreaAddSymbolLayer.source = editAreaAddSymbol.sourceId
        editAreaAddSymbolLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
        editAreaAddSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
        editAreaAddSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
//        editAreaSymbolLayer.iconOffset
//        editAreaSymbolLayer.textOffset
        try? mapView.mapboxMap.style.addLayer(editAreaAddSymbolLayer)
    }

    /**
     * NGA Editポイントレイヤー
     */
    private func editAreaSymbolLayer() {
        editAreaSymbol.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(editAreaSymbol.source, id: editAreaSymbol.sourceId)

        var editAreaSymbolLayer = SymbolLayer(id: editAreaSymbol.layerId)
        editAreaSymbolLayer.source = editAreaSymbol.sourceId
        editAreaSymbolLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
        editAreaSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
        editAreaSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
//        editAreaSymbolLayer.iconOffset
//        editAreaSymbolLayer.textOffset
        try? mapView.mapboxMap.style.addLayer(editAreaSymbolLayer)
    }

    /**
     * NGA Editライン表示レイヤー
     */
    private func editAreaLineLayer() {
        editAreaLine.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(editAreaLine.source, id: editAreaLine.sourceId)

        var editAreaLineLayer = LineLayer(id: editAreaLine.layerId)
        editAreaLineLayer.source = editAreaLine.sourceId
        editAreaLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        editAreaLineLayer.lineWidth = .expression(Exp(.get) {PropertyKey.LineWidth.rawValue})
        try? mapView.mapboxMap.style.addLayer(editAreaLineLayer)
    }

    /**
     * NGA Editエリアレイヤー
     */
    private func editAreaFillLayer() {
        editAreaFill.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(editAreaFill.source, id: editAreaFill.sourceId)

        var editAreaFillLayer = FillLayer(id: editAreaFill.layerId)
        editAreaFillLayer.source = editAreaFill.sourceId
        editAreaFillLayer.fillColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        try? mapView.mapboxMap.style.addLayer(editAreaFillLayer)
    }

    /**
     * NGAライン表示レイヤー
     */
    private func alertAreaLineLayer() {
        alertAreaLine.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(alertAreaLine.source, id: alertAreaLine.sourceId)

        var alertAreaLineLayer = LineLayer(id: alertAreaLine.layerId)
        alertAreaLineLayer.source = alertAreaLine.sourceId
        alertAreaLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        alertAreaLineLayer.lineWidth = .expression(Exp(.get) {PropertyKey.LineWidth.rawValue})
        try? mapView.mapboxMap.style.addLayer(alertAreaLineLayer)
    }

    /**
     * NGA エリアレイヤー
     */
    private func alertAreaFillLayer() {
        alertAreaFill.source.data = .featureCollection(FeatureCollection(features: []))
        try! mapView.mapboxMap.style.addSource(alertAreaFill.source, id: alertAreaFill.sourceId)

        var alertAreaFillLayer = FillLayer(id: alertAreaFill.layerId)
        alertAreaFillLayer.source = alertAreaFill.sourceId
        alertAreaFillLayer.fillColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
        alertAreaFillLayer.fillOpacity = .expression(Exp(.get) {PropertyKey.FillOpacity.rawValue})
        try? mapView.mapboxMap.style.addLayer(alertAreaFillLayer)
    }

    /**
     * 自船シンボル描画処理
     */
    func updateOwnShipSymbol(location: CLLocationCoordinate2D, bearing: Double){
        do {
            var shipIcon = IconImage.OwnShip_Normal.rawValue

            switch SharingData.location.status {
            case ShipAlert.Offline:
                shipIcon = IconImage.OwnShip_Offline.rawValue
            case ShipAlert.Unknown:
                shipIcon = IconImage.OwnShip_Unknown.rawValue
            case ShipAlert.Normal:
                shipIcon = IconImage.OwnShip_Normal.rawValue
            case ShipAlert.Caution:
                shipIcon = IconImage.OwnShip_Caution.rawValue
            case ShipAlert.Warrning:
                shipIcon = IconImage.OwnShip_Warning.rawValue
            case ShipAlert.Alarm:
                shipIcon = IconImage.OwnShip_Alarm.rawValue
            case ShipAlert.Emergency:
                shipIcon = IconImage.OwnShip_Emergency.rawValue
            case ShipAlert.NecstEmergency:
                shipIcon = IconImage.OwnShip_NeCST_Emergency.rawValue
            }

            var geoJSON = Feature(geometry: Point(location))
            geoJSON.properties = [PropertyKey.Bearing.rawValue: .number(bearing),
                                  PropertyKey.IconImage.rawValue: .string(shipIcon)]
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: self.ownShipSymbol.sourceId, geoJSON: .feature(geoJSON))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * ECA表示
     */
    func updateEcaSwitchingLine(center: CLLocationCoordinate2D, notice: Float, start: Float, finish: Float) {
        do{
            var switchingLines : [Feature] = []
            var switchingLabels : [Feature] = []

            let circlePoints_notice = getCirclePoints(center: center, radiusKm: LocationCalculation.nm2km(nm: Double(notice)))
            var noticeLine = Feature(geometry: LineString(circlePoints_notice))
            noticeLine.properties = [PropertyKey.Color.rawValue: .string("#62AB28")]
            switchingLines.append(noticeLine)
            if let point = circlePoints_notice.first{
                var label = Feature(geometry: Point(point))
                label.properties = [PropertyKey.Text.rawValue: .string("Advance Notice"),
                                    PropertyKey.IconImage.rawValue: .string(IconImage.SwNoticeBack.rawValue),
                                    PropertyKey.Color.rawValue: .string("#62AB28")]
                switchingLabels.append(label)
            }

            let circlePoints_start = getCirclePoints(center: center, radiusKm: LocationCalculation.nm2km(nm: Double(start)))
            var startLine = Feature(geometry: LineString(circlePoints_start))
            startLine.properties = [PropertyKey.Color.rawValue: .string("#ECD932")]
            switchingLines.append(startLine)
            if let point = circlePoints_start.first{
                var label = Feature(geometry: Point(point))
                label.properties = [PropertyKey.Text.rawValue: .string("Switching Start"),
                                    PropertyKey.IconImage.rawValue: .string(IconImage.SwStartBack.rawValue),
                                    PropertyKey.Color.rawValue: .string("#ECD932")]
                switchingLabels.append(label)
            }

            let circlePoints_finish = getCirclePoints(center: center, radiusKm: LocationCalculation.nm2km(nm: Double(finish)))
            var finishLine = Feature(geometry: LineString(circlePoints_finish))
            finishLine.properties = [PropertyKey.Color.rawValue: .string("#EF6135")]
            switchingLines.append(finishLine)
            if let point = circlePoints_finish.first{
                var label = Feature(geometry: Point(point))
                label.properties = [PropertyKey.Text.rawValue: .string("Switching Finish"),
                                    PropertyKey.IconImage.rawValue: .string(IconImage.SwFinisheBack.rawValue),
                                    PropertyKey.Color.rawValue: .string("#EF6135")]
                switchingLabels.append(label)
            }

            let lineGeoJson = FeatureCollection(features: switchingLines)
            let labelGeoJson = FeatureCollection(features: switchingLabels)
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson))
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * ECA消去
     */
    func removeEcaSwitchingLine() {
        do{
            let switchingLines : [Feature] = []
            let switchingLabels : [Feature] = []

            let lineGeoJson = FeatureCollection(features: switchingLines)
            let labelGeoJson = FeatureCollection(features: switchingLabels)
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson))
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * ECAライン更新
     */
    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 {
            print(debug: "called")
        }
    }

    /**
     * ECAライン消去
     */
    func removeEcaLine(){
        do{
            let line: [CLLocationCoordinate2D] = []
            let geoJson = Feature(geometry: LineString(line))
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson))
        } catch {
            print(debug: "called")
        }
    }

    ///一時的に見たいEcaを表示
    func updateOneTimeEca(eca: [CLLocationCoordinate2D]?) {
        do {
            let eca = eca ?? []
            var geoJson = Feature(geometry: LineString(eca))
            geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.black.description)]

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: oneTimeEca.sourceId, geoJSON: .feature(geoJson))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * 航跡ライン更新処理
     */
    func updateWakeLines(legLine: [CLLocationCoordinate2D], portLine: [CLLocationCoordinate2D], starboardLine: [CLLocationCoordinate2D]) {
        do{
            var legLineFeature = Feature(geometry: LineString(legLine))
            legLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]

            var portLineFeature = Feature(geometry: LineString(portLine))
            portLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]

            var starboardLineFeature = Feature(geometry: LineString(starboardLine))
            starboardLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: wakeLines.sourceId, geoJSON: .featureCollection(FeatureCollection(features: [legLineFeature, portLineFeature, starboardLineFeature])))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * wayポイント更新処理
     */
    func updateWayPoints(points: [CLLocationCoordinate2D]) {
        do {
            var features : [Feature] = []

            for point in points {
                var feature = Feature(geometry: Point(point))
                feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.SwFinisheBack.rawValue),
                                      PropertyKey.Color.rawValue: .string("#EF6135")]
                features.append(feature)
            }

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA Editターゲット更新処理
     */
    private func updateEditTargetSymbol(point: CLLocationCoordinate2D, remove: Bool = false) {
        do {
            var features : [Feature] = []
            if remove == false {
                var feature = Feature(geometry: Point(point))
                feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.Target.rawValue),
                                      PropertyKey.Color.rawValue: .string("#EF6135"),
                                      PropertyKey.Size.rawValue: 1.0]
                features.append(feature)
            }

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editTargetSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA Edit更新処理
     *  remove:
     *      true:画面消去
     *      false:画面表示
     */
    func updateEditArea(remove: Bool = false) {
        if let area = SharingData.nga.editNga {
            if remove {
                updateEditAreaAddSymbol(points: area.points, remove: remove)
                updateEditAreaSymbol(points: area.points, remove: remove)
                updateEditAreaLine(points: area.points, remove: remove)
                updateEditAreaFill(points: area.points, remove: remove)
            } else {
                if area.points.count != 0 {
                    //            updateEditAreaLabel(points: points)
                    updateEditAreaSymbol(points: area.points, remove: remove)
                }

                if area.points.count >= 2 {
                    updateEditAreaLine(points: area.points, remove: remove)
                }

                var areaPoints: [CLLocationCoordinate2D] = []
                if remove == true {
                    updateEditAreaFill(points: areaPoints, remove: remove)
                    updateEditAreaAddSymbol(points: areaPoints, remove: remove)
                } else {
                    if area.points.count >= 3 {
                        areaPoints = area.points
                        areaPoints.append(area.points[0])
                        updateEditAreaFill(points: areaPoints, remove: true)

                        updateEditAreaFill(points: areaPoints, remove: false)
                        updateEditAreaAddSymbol(points: areaPoints, remove: false)
                    }
                }
            }
        }
    }

    func updateEditTarget() {
        if SharingData.nga.editType == EditNgaType.movePoint {
            if let location = SharingData.nga.targetLocation {
                updateEditTargetSymbol(point: location)
            }
        } else {
            let location = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
            updateEditTargetSymbol(point: location, remove: true)
        }
    }

    /**
     * NGA Edit 追加シンボル更新処理
     */
    private func updateEditAreaAddSymbol(points: [CLLocationCoordinate2D], remove: Bool = false) {
        do{
            var features : [Feature] = []
            var id = 1
            var firstPass = false

            if remove == false {
                var pointA = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
                var pointB = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
                for point in points {
                    if firstPass == true {
                        pointB = point

                        let harf = LocationCalculation.halfPoint(posA: pointA, posB: pointB)
                        var feature = Feature(geometry: Point(harf))
                        feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.AddSymbol.rawValue),
                                              PropertyKey.Id.rawValue: .string(String(id)),
                                              PropertyKey.Dtype.rawValue: .string(DataType.add.rawValue),
                                              PropertyKey.Color.rawValue: .string("#62AB28")]
                        features.append(feature)
                        id += 1
                        pointA = pointB
                    } else {
                        pointA = point
                        firstPass = true
                    }
                }
            }

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaAddSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA Editポイント更新処理
     */
    private func updateEditAreaSymbol(points: [CLLocationCoordinate2D], remove: Bool = false) {
        do {
            var features : [Feature] = []
            var id = 0

            if remove == false {
                for point in points {
                    var feature = Feature(geometry: Point(point))
                    feature.properties = [PropertyKey.Text.rawValue: .string(String(id + 1)),
                                          PropertyKey.IconImage.rawValue: .string(IconImage.AreaPoint.rawValue),
                                          PropertyKey.Id.rawValue: .string(String(id)),
                                          PropertyKey.Dtype.rawValue: .string(DataType.point.rawValue),
                                          PropertyKey.Color.rawValue: .string("#EF6135")]
                    features.append(feature)
                    id += 1
                    print(debug: "Test: point \(id)")
                }
            }
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA Editライン更新処理
     */
    private func updateEditAreaLine(points: [CLLocationCoordinate2D], remove: Bool = false) {
        do {
            var features : [Feature] = []
            var id = 0

            if remove == false {
                if points.count >= 3 {
                    for cnt in 0..<points.count {
                        var line : [CLLocationCoordinate2D] = []
                        line.append(points[cnt])
                        if cnt + 1 == points.count {
                            line.append(points[0])
                        } else {
                            line.append(points[cnt + 1])
                        }
                        var feature = Feature(geometry: LineString(line))
                        feature.properties = [PropertyKey.Color.rawValue: .string(Color.black.description),
                                              PropertyKey.Id.rawValue: .string(String(id)),
                                              PropertyKey.Dtype.rawValue: .string(DataType.line.rawValue),
                                              PropertyKey.LineWidth.rawValue: 3.0]
                        features.append(feature)
                        id += 1
                    }
                } else if points.count == 2 {
                    var line : [CLLocationCoordinate2D] = []
                    line.append(points[0])
                    line.append(points[1])
                    var feature = Feature(geometry: LineString(line))
                    feature.properties = [PropertyKey.Color.rawValue: .string(Color.black.description),
                                          PropertyKey.Id.rawValue: .string(String(id)),
                                          PropertyKey.Dtype.rawValue: .string(DataType.line.rawValue),
                                          PropertyKey.LineWidth.rawValue: 1.0]
                    features.append(feature)
                }
            }
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaLine.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA Editエリア更新処理
     */
    private func updateEditAreaFill(points: [CLLocationCoordinate2D], remove: Bool = false) {
        do{
            var features : [Feature] = []

            if remove == false {
                var cnvPoints: Array<Array<CLLocationCoordinate2D>> = []
                var areaPoints = points
                let firstPoint = points[0]
                areaPoints.append(firstPoint)

                cnvPoints.append(areaPoints)
                var feature = Feature(geometry: Polygon(cnvPoints))
                feature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
                features.append(feature)
            }

            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaFill.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA 更新処理
     */
    func updateAlertArea() {
        updateAlertAreaLine(area: SharingData.nga.ngaArea, edit: SharingData.nga.editNga, type: SharingData.nga.editType)
        updateAlertAreaFill(area: SharingData.nga.ngaArea, edit: SharingData.nga.editNga, type: SharingData.nga.editType)
    }

    /**
     * NGA ポイント更新処理
     */
    private func updateAlertAreaSymbol(area: Dictionary<UUID, RegisteredNga>) {
        do{
            var features : [Feature] = []
            for (_, value) in area {
                if value.points.count >= 3 {
                    for point in value.points {
                        var feature = Feature(geometry: Point(point))
                        feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.AreaPoint.rawValue),
                                              PropertyKey.Color.rawValue: .string(Color.black.description)]
                        features.append(feature)
                    }
                }
            }
            let featureCollection = FeatureCollection(features: features)
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaSymbol.sourceId, geoJSON: .featureCollection(featureCollection))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGAライン更新処理
     */
    private func updateAlertAreaLine(area: Dictionary<UUID, RegisteredNga>,
                                     edit: RegisteredNga?,
                                     type: EditNgaType) {
        do{
            var features : [Feature] = []
            for (_, value) in area {
                var isEdit = true
                if let editId = edit?.areaId {
                    if value.areaId == editId && type != EditNgaType.nonEdit {
                        isEdit = false
                    }
                }
                if value.isRunning == true && isEdit == true {
                    if value.points.count >= 3 {
                        var areaPoints = value.points
                        let firstPoint = value.points[0]
                        areaPoints.append(firstPoint)

                        var color = Color.white.description
                        if value.isRunning {
                            color = Color.red.description
                        }
                        var feature = Feature(geometry: LineString(areaPoints))
                        feature.properties = [PropertyKey.Color.rawValue: .string(color),
                                              PropertyKey.LineWidth.rawValue: 1.0]
                        features.append(feature)
                    }
                }
            }
            let featureCollection = FeatureCollection(features: features)
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaLine.sourceId, geoJSON: .featureCollection(featureCollection))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * NGA エリア更新処理
     */
    private func updateAlertAreaFill(area: Dictionary<UUID, RegisteredNga>,
                                     edit: RegisteredNga?,
                                     type: EditNgaType) {
        do{
            var features : [Feature] = []
            for (_, value) in area {
                var isEdit = true
                if let editId = edit?.areaId {
                    if value.areaId == editId && type != EditNgaType.nonEdit {
                        isEdit = false
                    }
                }
                if value.points.count >= 3 && isEdit == true {
                    var cnvPoints: Array<Array<CLLocationCoordinate2D>> = []
                    
                    var areaPoints = value.points
                    let firstPoint = value.points[0]
                    areaPoints.append(firstPoint)

                    cnvPoints.append(areaPoints)
                    var feature = Feature(geometry: Polygon(cnvPoints))
                    if value.isRunning {
                        feature.properties = [PropertyKey.Color.rawValue: .string(value.color),
                                              PropertyKey.FillOpacity.rawValue: 1.0]
                    } else {
                        feature.properties = [PropertyKey.Color.rawValue: .string(value.color),
                                              PropertyKey.FillOpacity.rawValue: 0.2]
                    }
                    features.append(feature)
                }
            }

            let featureCollection = FeatureCollection(features: features)
            try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaFill.sourceId, geoJSON: .featureCollection(featureCollection))
        } catch {
            print(debug: "called")
        }
    }

    /**
     * カメラ
     */
    func updateCamera(location: CLLocationCoordinate2D?, zoomlevel: CGFloat?){
        if let level = zoomlevel {
            self.mapView.camera.ease(to: CameraOptions(center: location, zoom: level), duration: 1)
        } else {
            self.mapView.camera.ease(to: CameraOptions(center: location), duration: 1)
        }
        if SharingData.eca.focusEca != nil {
            SharingData.eca.focusEca = nil
        }
        if SharingData.nga.focusNga != nil {
            SharingData.nga.focusNga = nil
        }
        if SharingData.pushHistory.focusPushHistory != nil {
            SharingData.pushHistory.focusPushHistory = nil
        }
        if SharingData.location.focusOwnShip {
            SharingData.location.focusOwnShip = false
        }
    }

    /**
     * 子午線を跨ぐ位置情報をチェックして東経ベースに補正する。
     */
    static func checkStraddleMeridian(_ locations: [CLLocationCoordinate2D]) -> [CLLocationCoordinate2D] {
        let eastLon = FloatingPointSign.plus
        var returnLocations : [CLLocationCoordinate2D] = []
        for location in locations {
            if location.longitude.sign != eastLon{
                var loc = location
                loc.longitude += 360
                returnLocations.append(loc)
            }else{
                returnLocations.append(location)
            }
        }
        return returnLocations
    }

    /**
     * 円の位置情報を返す
     */
    private func getCirclePoints(center: CLLocationCoordinate2D, radiusKm: Double) -> [CLLocationCoordinate2D]{
        var circlePoints : [CLLocationCoordinate2D] = []
        for deg in stride(from: 0, through: 360, by: 6) {
            let point = LocationCalculation.findPointAtDistanceFrom(
                startPointLat: center.latitude,
                startPointLon: center.longitude,
                initialBearing: Double(deg),
                distanceKilometers: radiusKm
            )
            circlePoints.append(point)
        }
        return circlePoints
    }

    enum PropertyKey : String {
        case Id
        case Dtype
        case IconImage
        case Bearing
        case Color
        case Text
        case Size
        case LineWidth
        case FillOpacity
        case FillOutlineColor
    }

    enum DataType : String {
        case ownShip
        case point
        case line
        case add
    }

    /**
     * 地図上クリック
     */
    func mapClick(point: CGPoint, coordinate: CLLocationCoordinate2D) {
        let layers = [
            ownShipSymbol.layerId,
            editAreaSymbol.layerId,
            editAreaAddSymbol.layerId
        ]

        self.touchedFeatures = nil
        var features : [Feature] = []
        let option = RenderedQueryOptions(layerIds: layers, filter: nil)

        mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
            switch result {
            case .success(let queriedFeature):
                for feature in queriedFeature {
                    features.append(feature.feature)
                }
                if let feature = features.last {
                    self.touchedFeatures = feature
                }
                clickSymbolLayer(tatchPoint: point, coordinate: coordinate)
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }

    /**
     * ポイントクリック処理
     */
    private func clickSymbolLayer(tatchPoint: CGPoint, coordinate: CLLocationCoordinate2D) {
        if let targetFeature = self.touchedFeatures {
            guard let type = targetFeature.properties?[PropertyKey.Dtype.rawValue] else {return}

            switch type! {
            case Turf.JSONValue.string(DataType.point.rawValue):
                guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
                guard let Id = jsonData?.rawValue else {return}

                if let noStr = Id as? String {
                    if let no = Int(noStr) {
                        SharingData.nga.selectPoint = no
                    }
                }

                if SharingData.nga.editNga?.isLock == false {
                    SharingData.nga.editType = EditNgaType.movePoint
                    SharingData.nga.moveNga = SharingData.nga.editNga
                    lockEditPoint(isLocked: false)  //地図を固定

                    updateEditTargetSymbol(point: coordinate)
                }
            case Turf.JSONValue.string(DataType.add.rawValue):
                guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
                guard let Id = jsonData?.rawValue else {return}

                if SharingData.nga.editNga?.isLock == false {
                    if let noStr = Id as? String {
                        if let no = Int(noStr) {
                            SharingData.nga.editNga?.points.insert(coordinate, at: no)
                        }
                    }
                }
            default:
                if SharingData.nga.editType == EditNgaType.addPoint {
                    if let editNga = SharingData.nga.editNga {
                        if editNga.points.count < ngaAreaPointMax {
                            SharingData.nga.editNga?.points.append(coordinate)
                        }
                    }
                }
            }
        } else {
            if SharingData.nga.editType == EditNgaType.addPoint {
                if let editNga = SharingData.nga.editNga {
                    if editNga.points.count < ngaAreaPointMax {
                        SharingData.nga.editNga?.points.append(coordinate)
                    }
                }
            }
            if SharingData.nga.editType == EditNgaType.movePoint {
                SharingData.nga.editType = EditNgaType.addPoint
                SharingData.map.isMapFree = true
            }
        }
    }

    /**
     * 地図上ロングクリック
     */
    func mapLongClick(point: CGPoint, coordinate: CLLocationCoordinate2D) {
        let layers = [
            editAreaSymbol.layerId
        ]

        self.touchedFeatures = nil
        var features : [Feature] = []
        let option = RenderedQueryOptions(layerIds: layers, filter: nil)

        mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
            switch result {
            case .success(let queriedFeature):
                for feature in queriedFeature {
                    features.append(feature.feature)
                }
                if let feature = features.last {
                    self.touchedFeatures = feature
                }

                longClickSymbolLayer(tatchPoint: point, coordinate: coordinate)
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }

    /**
     * ポイント削除
     */
    private func longClickSymbolLayer(tatchPoint: CGPoint, coordinate: CLLocationCoordinate2D) {
        if SharingData.nga.editType == EditNgaType.addPoint {
            if let targetFeature = self.touchedFeatures {
                guard let type = targetFeature.properties?[PropertyKey.Dtype.rawValue] else {return}

                if type! == Turf.JSONValue.string(DataType.point.rawValue) {
                    guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
                    guard let Id = jsonData?.rawValue else {return}

                    if let noStr = Id as? String {
                        if let no = Int(noStr) {
                            SharingData.nga.editType = EditNgaType.deletePoint
                            SharingData.nga.selectPoint = no
                        }
                    }
                }
                updateEditArea()
            }
        }
    }

    /**
     * ポイント削除（後処理）
     */
    func deleteSymbol() {
        if let no = SharingData.nga.selectPoint {
            SharingData.nga.editNga?.points.remove(at: no)
            SharingData.nga.selectPoint = nil
        }
        SharingData.nga.editType = EditNgaType.addPoint
    }

    /**
     *　地図上ドラッグ
     */
    private func mapDrug(point: CGPoint, coordinate: CLLocationCoordinate2D) {
        let layers = [
            editAreaSymbol.layerId
        ]

        self.touchedFeatures = nil
        var features : [Feature] = []
        let option = RenderedQueryOptions(layerIds: layers, filter: nil)

        mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
            switch result {
            case .success(let queriedFeature):
                for feature in queriedFeature {
                    features.append(feature.feature)
                }
                if let feature = features.last {
                    self.touchedFeatures = feature
                }
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }

    /**
     * ポイントの選択状態の設定
     *  setUserMarkRock
     */
    func lockEditPoint(isLocked: Bool){
        let drug = UIPanGestureRecognizer(target: self, action: #selector(handleMapDrug))
        if isLocked {
            mapView.removeGestureRecognizer(drug)
            for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer {
                recognizer.isEnabled = true
            }
        } else {
            for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer {
                recognizer.isEnabled = false
                drug.require(toFail: recognizer)
            }
            mapView.addGestureRecognizer(drug)
        }
    }
}
