//
//  MapViewController.swift
//  BookCore
//
//  coeded by 日々野清高 on 2023/01/19.
//

import Foundation
import UIKit
import MapKit
import PlaygroundSupport
import AVFoundation
import CoreLocation


public class MapViewController: UIViewController, MKMapViewDelegate, PlaygroundLiveViewSafeAreaContainer  {
    private var myIpTextView  = UITextView()
    private let textView = UITextView()
    private var mapView = MKMapView()
    private var annotationColor = UIColor()
    private var calloutEnable = false
    public required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }
    
    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    }


    public override func viewDidLoad() {
        super.viewDidLoad()
        
        //自分のIPアドレス表示ビューを配置
        myIpTextView.font = UIFont.monospacedSystemFont(ofSize: 20, weight: .medium)
        myIpTextView.isEditable = false
         view.addSubview(myIpTextView)
        //myIpTextView.textColor = .white
        // textColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        //myIpTextView.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        myIpTextView.translatesAutoresizingMaskIntoConstraints  = false
        myIpTextView.topAnchor.constraint(equalTo: liveViewSafeAreaGuide.topAnchor, constant: 10).isActive = true
        myIpTextView.bottomAnchor.constraint(equalTo: liveViewSafeAreaGuide.topAnchor, constant: 40).isActive = true
        myIpTextView.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor, constant: 20).isActive = true
        myIpTextView.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -20).isActive = true
        
        //このデバイスのipアドレスを取得してipAddressTextViewに表示
        myIpTextView.text = "このデバイスのIPアドレス：" + getIPV4Address()
        
        annotationColor = .red
        //view.backgroundColor = #colorLiteral(red: 0.1764705926, green: 0.4980392158, blue: 0.7568627596, alpha: 1)
        // disable auto layout
        view.translatesAutoresizingMaskIntoConstraints = false
        
        // 緯度・軽度を設定
        let location:CLLocationCoordinate2D
            = CLLocationCoordinate2DMake(35.709861,139.810770)
        mapView.setCenter(location,animated:true)
 
        // 縮尺を設定
        var region:MKCoordinateRegion = mapView.region
        region.center = location
        region.span.latitudeDelta = 0.02
        region.span.longitudeDelta = 0.02
 
        mapView.setRegion(region,animated:true)
 
        // 表示タイプを航空写真と地図のハイブリッドに設定
        mapView.mapType = MKMapType.standard
        // mapView.mapType = MKMapType.hybrid
        // mapView.mapType = MKMapType.satellite
        
        view.addSubview(mapView)
        // 長押しのUIGestureRecognizerを生成.
        let myLongPress: UILongPressGestureRecognizer = UILongPressGestureRecognizer()
        myLongPress.addTarget(self, action: #selector(recognizeLongPress(sender:)))

        // MapViewにUIGestureRecognizerを追加.
        mapView.addGestureRecognizer(myLongPress)
        
        //mapView.isUserInteractionEnabled = true
        mapView.delegate = self
        mapView.clipsToBounds = true //はみ出さない様にする。
        //mapView.backgroundColor  = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
        mapView.layer.cornerRadius = 10
        mapView.translatesAutoresizingMaskIntoConstraints  = false
        mapView.topAnchor.constraint(equalTo: myIpTextView.bottomAnchor, constant: 5).isActive = true
        mapView.bottomAnchor.constraint(equalTo: liveViewSafeAreaGuide.bottomAnchor, constant: -40).isActive = true
        mapView.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor, constant: 20).isActive = true
        mapView.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -20).isActive = true
        mapView.showsCompass = true
        mapView.showsScale = true
        mapView.showsUserLocation = true
        mapView.isUserInteractionEnabled = true
        mapView.isPitchEnabled = true
        
        //メッセージ表示用のビューを配置
        textView.font = UIFont.monospacedSystemFont(ofSize: 20, weight: .medium)
        textView.isEditable = false
        view.addSubview(textView)
        //textView.textColor = .white
        textView.translatesAutoresizingMaskIntoConstraints  = false
        textView.topAnchor.constraint(equalTo: mapView.bottomAnchor, constant: 10).isActive = true
        textView.bottomAnchor.constraint(equalTo: liveViewSafeAreaGuide.bottomAnchor, constant: 0).isActive = true
        textView.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor, constant: 20).isActive = true
        textView.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -20).isActive = true
        
    }

    @objc func recognizeLongPress(sender: UILongPressGestureRecognizer) {
        // 長押しの最中に何度もピンを生成しないようにする.
        if sender.state != UIGestureRecognizer.State.began {
            return
        }
        // 長押しした地点の座標を取得.
        let point = sender.location(in: mapView)
        // locationをCLLocationCoordinate2Dに変換.
        let coordinate: CLLocationCoordinate2D = mapView.convert(point, toCoordinateFrom: mapView)
        // ピンを生成.
        let annotation: MKPointAnnotation = MKPointAnnotation()
        // 座標を設定.
        annotation.coordinate = coordinate
        // 位置情報から住所を取得してタイトルにセット
        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) { placemarks, error in
            guard let placemark = placemarks?.first, error == nil else { return }
            // アノテーションのタイトルを住所にする
            annotation.title = placemark.administrativeArea! + placemark.locality! + placemark.name!
        }
        annotation.subtitle = "\(coordinate.latitude),\(coordinate.longitude)"
        // MapViewにピンを追加.
        mapView.addAnnotation(annotation)
    }
    public override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    //アノテーションが押されたときのイベント
    public func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        // タップされたピンの位置情報
        print(view.annotation?.coordinate as Any)
        // タップされたピンのタイトルとサブタイトル
        print(view.annotation?.title as Any)
        print(view.annotation?.subtitle as Any)
    }
    //アノテーションをタップした時に吹き出しにUIButtonをセット
    public func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {
        for view in views {
            view.rightCalloutAccessoryView = UIButton(type: UIButton.ButtonType.detailDisclosure)
        }
    }
    //アノテーションの吹き出しを押された時に呼び出されるイベント
    public func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
        if(calloutEnable) {
            //let titleStr :String = (view.annotation?.title ?? "")!
            let subtitleStr :String = (view.annotation?.subtitle ?? "")!
            //textView.insertText("\(titleStr):\(subtitleStr)\n")
            calloutTapped(str: subtitleStr)
        }
    }
    
    //アノテーションを返すメソッド
    public func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
               var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "myAnnotation") as? MKMarkerAnnotationView
        
               if annotationView == nil {
                   annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotation")
               } else {
                   annotationView?.annotation = annotation
               }
               if let annotation = annotation as? MyPointAnnotation {
                   annotationView?.markerTintColor = annotation.tintColor
               }
        
               annotationView?.isDraggable = true
               annotationView?.displayPriority = .required
               annotationView?.canShowCallout = true
               annotationView?.clusteringIdentifier = nil
               annotationView?.animatesWhenAdded = true
               return annotationView
           }

}

class MyPointAnnotation : MKPointAnnotation {
    var tintColor: UIColor?
}


extension MapViewController: PlaygroundLiveViewMessageHandler {
    //Playgroundページからメッセージを受け取る際の処理。
    public func receive(_ message: PlaygroundValue) {
        
        if case let .string(text) = message {
            if(text == "clear") { //クリア命令
                let allAnnotations = mapView.annotations
                mapView.removeAnnotations(allAnnotations)
                return
            } else if (text == "enable") {
                calloutEnable = true
                return
            } else if (text == "disable") {
                calloutEnable = false
                return
            }
            //スペース区切りで引数を配列にセット
            let arr:[String] = text.components(separatedBy: " ")
            
            if(arr.count == 2) {
                if(arr[0] == "color") {
                    let cnumber = Int(arr[1])
                    if(cnumber == 0) {
                        annotationColor = .black
                    } else if (cnumber == 1) {
                        annotationColor = .red
                    } else if (cnumber == 2) {
                        annotationColor = .green
                    } else if (cnumber == 3) {
                        annotationColor = .blue
                    } else if (cnumber == 4) {
                        annotationColor = .yellow
                    } else if (cnumber == 5) {
                        annotationColor = .purple
                    }
                    return
                }
                if(arr[0] == "type") {
                    let ynumber = Int(arr[1])
                    switch ynumber {
                    case 0:
                        mapView.mapType = MKMapType.standard
                        break
                    case 1:
                        mapView.mapType = MKMapType.satellite
                        break
                    case 2:
                        mapView.mapType = MKMapType.hybrid
                        break
                    case 3:
                        mapView.mapType = MKMapType.hybridFlyover
                        break
                    case 4:
                        mapView.mapType = MKMapType.mutedStandard
                        break
                    default:
                        break
                    }
                    return
                }
            }
            if(arr.count == 4) {
                if(arr[0] == "mark") {
                    let title = arr[1]
                    let latitude = Double(arr[2])!
                    let longitude = Double(arr[3])!
                    let coordinate = CLLocationCoordinate2DMake(latitude, longitude)
                    let pin = MyPointAnnotation()
                    pin.coordinate = coordinate
                    pin.title = title
                    // 位置情報から住所を取得してタイトルにセット
                    CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)) { placemarks, error in
                        guard let placemark = placemarks?.first, error == nil else { return }
                        // アノテーションのタイトルを住所にする
                        pin.title = title + placemark.administrativeArea! + placemark.locality! + placemark.name!
                    }
                    pin.subtitle = "\(coordinate.latitude),\(coordinate.longitude)"
                    pin.tintColor = annotationColor
                    mapView.addAnnotation(pin)
                }
                return
            }
            
            if(arr.count == 5 ){
                if(arr[0] == "color") { //色指定命令
                    let r = CGFloat(Double(arr[1])!)
                    let g = CGFloat(Double(arr[2])!)
                    let b = CGFloat(Double(arr[3])!)
                    let a = CGFloat(Double(arr[4])!)
                    annotationColor = UIColor(red: r, green: g, blue: b, alpha: a)
                }
                return
            }
            textView.text = textView.text + "\(text)\n"
            
        }
    }
    //Annotationのcalloutがタップされた時にページにメッセージを送る際のサンプル。
    public func calloutTapped(str: String) {
        let message: PlaygroundValue = .string(str)
        send(message)
    }
}
