//#-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
let page = PlaygroundPage.current

//private var connection : NWConnection!
page.needsIndefiniteExecution = true

func vprint(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string(str)
       proxy1.send(message)
   }
}
func s_print(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string("SEND " + str)
       proxy1.send(message)
   }
}
func r_print(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string("RECIVE " + str)
       proxy1.send(message)
   }
}
func ip_print(_ str: String) {
   if let proxy1 = page.liveView as? PlaygroundRemoteLiveViewProxy {
       let message: PlaygroundValue = .string("IP " + str)
       proxy1.send(message)
   }
}

//ボタンの処理
let proxy2 = page.liveView as? PlaygroundRemoteLiveViewProxy
class pgListener: PlaygroundRemoteLiveViewProxyDelegate {
    func remoteLiveViewProxy(_ remoteLiveViewProxy: PlaygroundRemoteLiveViewProxy,received message: PlaygroundValue) {
        if case let .string(text) = message {
            var str = text
            if(str.hasPrefix("TAPPED")) {
                tapped()
            }
        }
    }
    func remoteLiveViewProxyConnectionClosed(_ remoteLiveViewProxy: PlaygroundRemoteLiveViewProxy) {
    //コネクション切断時の処理
    }
}
let pglistener = pgListener()
proxy2?.delegate = pglistener

func send(connection: NWConnection, message: String) {
    // 送信データ生成
    let data = message.data(using: .utf8)!
    // データ送信
    connection.send(content: data, completion: .contentProcessed { error in
        if let error = error {
            vprint("\(#function): \(error.localizedDescription)")
            connection.cancel()
        }
    })
    // 送信完了待ち
}

func connect(host: String, port: String) -> NWConnection
{
    let t_host = NWEndpoint.Host(host)
    let t_port = NWEndpoint.Port(port)
    let connection : NWConnection
    //let semaphore = DispatchSemaphore(value: 0)
    /* コネクションの初期化 */
    connection = NWConnection(host: t_host, port: t_port!, using: .tcp)
    
    /* コネクションのStateハンドラ設定 */
    connection.stateUpdateHandler = { (newState) in
        switch newState {
        case .ready:
            //vprint("接続要求して送信準備ができました")
            //semaphore.signal()
            break
        case .waiting(let error):
            //vprint("waiting:\(#function), \(error)")
            break
        case .failed(let error):
            //vprint("failed:\(#function), \(error)")
            break
        case .setup: break
        case .cancelled: break
        case .preparing: break
        @unknown default:
            //vprint("Illegal state")
            break
        }
    }
    // コネクション開始
    let queue = DispatchQueue(label: "example")
    connection.start(queue:queue)
    
    // コネクション完了待ち
    //semaphore.wait()
    return connection
}

//#-end-hidden-code
/*: some text
 ##  💡2️⃣クライアント側
　このプログラムは、サーバープロラムに接続要求をして、接続が確立したら文字列「ON」を送信するクライアント側のプログラムです。\
　サーバーのIPアドレスを調べて、プログラムのIPアドレスを変更してください。
 * Important:
 別のiPadでサーバー側のプログラムを実行している状態でなければ接続できません。
 ---
 * Note:
 ライブビュー（右側のビュー）のボタンを押すと、このプログラムのtapped()が呼び出されます。\
 ボタンタップでON/OFFができるようにしましょう。
 ---
 */

//🖍️サーバーのIPアドレス
let host = "192.168.0.62"
//ポート番号
let port = "50000"

//サーバー側に接続してコネクションを確立
let connection = connect(host: host, port: port)

//コネクション経由でサーバーに"ON"メッセージを送信
send(connection: connection, message: "ON")


//🖍️ボタン押下時に呼び出される処理（解答例）
var flag = false
func tapped() {
    if(flag) {
        send(connection: connection, message: "ON")
    } else {
        send(connection: connection, message: "OFF")
    }
    flag.toggle()
}
