//#-hidden-code
//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  The Swift file containing the source code edited by the user of this playground book.
//

import PlaygroundSupport
import AudioToolbox
import Foundation
import Network
import UIKit

let page = PlaygroundPage.current
page.needsIndefiniteExecution = true

let 🔳 = 0
let 🟥 = 1
let 🟩 = 2
let 🟦 = 3
let 🟨 = 4
let 🟪 = 5

func vprint(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string(str)
       proxy1.send(message)
   }
}

func send(_ str: String) {
    if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
        let message: PlaygroundValue = .string(str)
        proxy1.send(message)
    }
}

func clear() {
    Thread.sleep(forTimeInterval: 0.5)
    send("clear")
}

func mark(_ title: String, _ latitude: Double, _ longitude: Double) {
    if(latitude < 0.0 || longitude < 0.0) {
        PlaygroundPage.current.assessmentStatus = .fail(hints: ["mark()の引数に範囲外の値が指定されています。緯度,経度の２つの値は0.0より大きい必要があります。"], solution: nil)
    } else {
        send("mark "+title+" "+latitude.description+" "+longitude.description)
    }
}

func type(_ t: Int) {
    if(t >= 0 && t < 5) {
        send("type "+t.description)
    } else {
        PlaygroundPage.current.assessmentStatus = .fail(hints: ["type()の引数に範囲外の値が指定されています。type()の括弧内には0〜4の整数型(Int)の数値を入れてください。"], solution: nil)
    }
}

func color(_ t: Int) {
    if(t >= 0 && t < 6) {
        send("color "+t.description)
    } else {
        PlaygroundPage.current.assessmentStatus = .fail(hints: ["color()の引数に範囲外の値が指定されています。color()の括弧内には0〜6の整数型(Int)の数値を入れてください。"], solution: nil)
    }
}
send("clear") //ピンを全削除
send("disable")//コールアウト無効

//#-end-hidden-code
/*: some text
##  🗺1️⃣サーバー側
　このサーバープログラムは、クライアントから受信した位置情報を地図にマークするものです。\
クライアントから送られるのは、「緯度」(latitude)と「軽度」(longitude)の情報です。

 * Note:
 地図のタイプは0〜4を指定できます。\
 mark("タイトル", latitude, longitude）で地図にマークできます。（タイトルには住所が追加されるので、絵文字などで短くしておきましょう）
 ---
 * Important:
 地図のタイプは0〜4まで指定できますが、を3D表示にするとSwiftPlaygroundsアプリが動作しなくなる時があります。
 ---
 */
//#-code-completion(everything, hide)

//地図のタイプ（標準）
type(0)
//ポート番号
private var port = NWEndpoint.Port(rawValue: 50000)!

// リスナーの起動
func startListener() {
    let listener = try! NWListener(using: .tcp, on: port)
    listener.newConnectionHandler = { newConnection in
        handleNewConnection(newConnection)
    }
    listener.start(queue: .main)
    vprint("リスナーを開始しました。")
}

// 新しい接続のハンドリング
func handleNewConnection(_ newConnection: NWConnection) {
    var remoteHost = ""
    switch(newConnection.endpoint) {
        case .hostPort(let host, _):
        let host = NWEndpoint.Host("\(host)")
            vprint("listener_\(host)からの接続がありました。")
            break
        default:
            break
    }
    let connection = newConnection
    connection.stateUpdateHandler = { newState in
    }
    connection.start(queue: .main)
    //🖍️位置情報を取得するための関数を呼び出す。
    //解答例
    receiveLocationData(connection: connection)
}

// 場所データの受信処理
func receiveLocationData(connection: NWConnection) {
    let bufferSize = 4096
    connection.receive(minimumIncompleteLength: 1, maximumLength: bufferSize) { data, _, isComplete, error in
        if let data = data, !data.isEmpty {
            let text = String(data: data, encoding: .utf8)!
            let strArray = text.split(separator: ",")
            let latitude = Double(strArray[0])!
            let longitude = Double(strArray[1])!
            //🖍️地図にマーカーを置くための関数を呼び出す。
            //解答例
            mark("⭐️", latitude, longitude)
            //マークした際に音を鳴らす。
            let soundIdRing:SystemSoundID = 1111
            AudioServicesPlaySystemSound(soundIdRing)
        }
        if isComplete || error != nil {
            //データ取得完了後にコネクションをキャンセル
            connection.cancel()
        }
    }
}

startListener()
