//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  A source file which is part of the auxiliary module named "BookCore".
//  Provides the implementation of the "always-on" live view.
//

import Foundation
import UIKit
import PlaygroundSupport
@preconcurrency import WebKit
import AudioToolbox
import Network

public class WebViewController: UIViewController, PlaygroundLiveViewMessageHandler, PlaygroundLiveViewSafeAreaContainer, WKUIDelegate, SetNameViewDelegate {
    public var pageIdentifier: String?
    private var userName: String? = nil
    private var userNumber: String? = nil
    //private let tcpClient = TCPClient()
    private let url = URL(string: "https://feedm.net/playgroundSupport/createHTML/session.php")!
    private var schoolId: String? = nil
    private var webMode: String? = nil
    private var currentSetNameView: SetNameView? = nil
    public var usernameLabel = UILabel()
    public var setUserButton = UIButton()
    
    private var webView = WKWebView()
    private var baseURL: URL?
    private let titleLabel = UILabel() // タイトル表示用のラベル
    private let containerView = UIView() // titleLabel と webView を含むビュー
    private let margin: CGFloat = 8 // マージンの設定

    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    public init() {
        super.init(nibName: nil, bundle: nil)
    }

    override public func viewDidLoad() {
        super.viewDidLoad()
        // PlaygroundKeyValueStoreからSchoolIdを取得
        if let keyValue = PlaygroundKeyValueStore.current["schoolId"],
           case .string(let storedSchoolId) = keyValue {
            schoolId = storedSchoolId
        } else {
            schoolId = nil
        }
        // PlaygroundKeyValueStoreからWebModeを取得
        if let keyValue = PlaygroundKeyValueStore.current["webMode"],
           case .string(let storedWebMode) = keyValue {
            webMode = storedWebMode
        } else {
            webMode = nil
        }
        // PlaygroundKeyValueStoreからユーザー名を取得
        if let keyValue = PlaygroundKeyValueStore.current["userName"],
            case .string(let storedUserName) = keyValue {
            userName = storedUserName
        } else {
            userName = nil
        }
        
        // PlaygroundKeyValueStoreから番号を取得
        if let keyValue = PlaygroundKeyValueStore.current["userNumber"],
            case .string(let storedNumber) = keyValue {
            userNumber = storedNumber
        } else {
            userNumber = nil
        }
        // ボタンの位置とサイズを設定
        setUserButton.frame = CGRect(x:160, y:80, width:120, height:30)
        // ボタンのタイトルを設定
        setUserButton.setTitle("ユーザー設定", for:UIControl.State.normal)
        // タイトルの色
        setUserButton.setTitleColor(UIColor.blue, for: .normal)
        // ボタンのフォントサイズ
        setUserButton.titleLabel?.font =  UIFont.systemFont(ofSize: 16)
        // 背景色
        setUserButton.backgroundColor = UIColor.init(
           red:0.9, green: 0.9, blue: 0.9, alpha: 0.5)
        setUserButton.layer.cornerRadius = 5
        // タップされたときのaction
        setUserButton.addTarget(self, action: #selector(self.showSetNameView), for: .touchUpInside)
        view.addSubview(setUserButton)
        //ユーザー名ラベルの位置とサイズを設定
        usernameLabel.frame = CGRect(x:150, y:80, width:400, height:30)
        usernameLabel.font = UIFont.systemFont(ofSize: 20)
        usernameLabel.text = [userNumber, userName].compactMap { $0 }.joined(separator: ":")
        view.addSubview(usernameLabel)
        
        setUserButton.translatesAutoresizingMaskIntoConstraints  = false
        usernameLabel.translatesAutoresizingMaskIntoConstraints  = false
        
        //let webViewConfiguration = WKWebViewConfiguration()
        //webViewConfiguration.preferences.javaScriptEnabled = true

        //webView = WKWebView(frame: .zero, configuration: webViewConfiguration)
        webView.uiDelegate = self  // WKUIDelegateを設定
        


        view.backgroundColor = .systemGray5.withAlphaComponent(0.9)
        view.translatesAutoresizingMaskIntoConstraints = false

        // containerView の設定
        containerView.backgroundColor = .white
        containerView.layer.cornerRadius = 8
        containerView.layer.masksToBounds = true
        containerView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(containerView)

        // titleLabel の設定
        titleLabel.textAlignment = .center
        titleLabel.backgroundColor = .systemBlue.withAlphaComponent(0.5)
        titleLabel.font = UIFont.boldSystemFont(ofSize: 16)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        containerView.addSubview(titleLabel)

        // webView の設定
        webView.translatesAutoresizingMaskIntoConstraints = false
        containerView.addSubview(webView)

        // containerView の制約
        NSLayoutConstraint.activate([
            setUserButton.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor,constant: margin),
            setUserButton.topAnchor.constraint(equalTo: liveViewSafeAreaGuide.topAnchor,constant: margin),
            setUserButton.heightAnchor.constraint(equalToConstant: 30.0),
            setUserButton.widthAnchor.constraint(equalToConstant: 140.0),
            
            usernameLabel.leadingAnchor.constraint(equalTo: setUserButton.trailingAnchor,constant: margin),
            usernameLabel.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -margin),
            usernameLabel.topAnchor.constraint(equalTo: liveViewSafeAreaGuide.topAnchor,constant: margin),
            usernameLabel.heightAnchor.constraint(equalToConstant: 30.0),
            
            containerView.topAnchor.constraint(equalTo: setUserButton.bottomAnchor, constant: margin),
            containerView.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor, constant: margin),
            containerView.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -margin),
            containerView.bottomAnchor.constraint(equalTo: liveViewSafeAreaGuide.bottomAnchor, constant: -margin),

            // containerView 内の titleLabel と webView の制約
            titleLabel.topAnchor.constraint(equalTo: containerView.topAnchor),
            titleLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            titleLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            titleLabel.heightAnchor.constraint(equalToConstant: 30),

            webView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor),
            webView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
            webView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor)
        ])
        
        // HTMLファイルのURLを取得し読み込み
        if let htmlFileURL = Bundle.main.url(forResource: "LiveView", withExtension: "html") {
            baseURL = htmlFileURL.deletingLastPathComponent()
            webView.loadFileURL(htmlFileURL, allowingReadAccessTo: baseURL!)
        }
        
        // WKWebViewのタイトルを監視する
        webView.navigationDelegate = self
    }

    public func liveViewMessageConnectionOpened() {
        // 接続が開かれたときの処理をここに実装します
    }

    public func liveViewMessageConnectionClosed() {
        // 接続が閉じられたときの処理をここに実装します
    }

    public func receive(_ message: PlaygroundValue) {
        // HTMLファイルのURLを取得し読み込み
        if let htmlFileURL = Bundle.main.url(forResource: "LiveView", withExtension: "html") {
            baseURL = htmlFileURL.deletingLastPathComponent()
            webView.loadFileURL(htmlFileURL, allowingReadAccessTo: baseURL!)
        }
        // Contents.swiftから送信されたメッセージを受け取るためのメソッド
            let codeText = PlaygroundPage.current.text
            // 取得した文字列から、ユーザー編集したものだけを取り出して出力
            let pattern = #"//#-editable-code\n([\s\S]*?)\n//#-end-editable-code"#
            var codetext = ""
            do {
                let regex = try NSRegularExpression(pattern: pattern, options: [])
                let nsRange = NSRange(codeText.startIndex..<codeText.endIndex, in: codeText)
                let matches = regex.matches(in: codeText, options: [], range: nsRange)
                // マッチした内容を取り出す
                for match in matches {
                    if let range = Range(match.range(at: 1), in: codeText) {
                        codetext += String(codeText[range]) + "\n"
                    }
                }
            } catch {
                codetext = "\n"
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
                self.webView.loadHTMLString(codetext, baseURL: self.baseURL)
            }
        
        if case let .string(text) = message {
            
            let arr:[String] = text.components(separatedBy: " ")
            var codetext = ""
            if(arr[0] == "message") {
                let codeText = PlaygroundPage.current.text
                // 取得した文字列から、ユーザー編集したものだけを取り出して出力
                let pattern = #"//#-editable-code\n([\s\S]*?)\n//#-end-editable-code"#
                do {
                    let regex = try NSRegularExpression(pattern: pattern, options: [])
                    let nsRange = NSRange(codeText.startIndex..<codeText.endIndex, in: codeText)
                    let matches = regex.matches(in: codeText, options: [], range: nsRange)
                    // マッチした内容を取り出す
                    for match in matches {
                        if let range = Range(match.range(at: 1), in: codeText) {
                            codetext += String(codeText[range]) + "\n"
                        }
                    }
                } catch {
                    codetext = "\n"
                }
                let message = (userNumber ?? "-") + "," + (userName ?? "未設定") + "," + text.suffix(text.count - 8)
                
                if (webMode == "Off") { //Bonjour送信の場合
                    let tcpClient = TCPClient()
                    // サービスの開始
                    tcpClient.start()
                    // 接続が確立された後にメッセージを送信するようにコールバックを設定
                    tcpClient.onConnectionReady = {
                        let messagedict: [String: String] = [
                            "message": message,
                            "code": codetext
                        ]
                        tcpClient.send(messageDict: messagedict)
                    }
                } else if (webMode == "On") { //Web送信の場合
                    //web送信の場合
                    let httpSend = HTTPSend(url: url)
                    httpSend.sendMessage(messageText: message, codeText:codetext, schoolId: schoolId ?? "") { result in
                        switch result {
                        case .success:
                            print("Message sent successfully")
                        case .failure(let error):
                            print("Failed to send message: \(error.localizedDescription)")
                        }
                    }
                    return
                }
            }
        }
    }
    
    @objc func showSetNameView() {
        // すでに SetNameView が表示されているかどうかを確認
        if currentSetNameView != nil {
            return
        }
        
        let setNameView = SetNameView()
        setNameView.delegate = self // デリゲートを設定
        setNameView.translatesAutoresizingMaskIntoConstraints = false
        // SetNameView を現在のプロパティに保持
        currentSetNameView = setNameView
        
        self.view.addSubview(setNameView)
        
        NSLayoutConstraint.activate([
            setNameView.leadingAnchor.constraint(equalTo: liveViewSafeAreaGuide.leadingAnchor,constant: 40.0),
            setNameView.trailingAnchor.constraint(equalTo: liveViewSafeAreaGuide.trailingAnchor, constant: -40.0),
            setNameView.topAnchor.constraint(equalTo: liveViewSafeAreaGuide.topAnchor, constant: 70.0),
            setNameView.bottomAnchor.constraint(equalTo: liveViewSafeAreaGuide.bottomAnchor, constant: -70)
        ])
    }
    
    func didSaveSettings(userName: String?, userNumber: String?) {
        self.userName = userName
        self.userNumber = userNumber
        usernameLabel.text = [userNumber, userName].compactMap { $0 }.joined(separator: ":")
        currentSetNameView?.removeFromSuperview()
        currentSetNameView = nil
    }
    func didCloseSetNameView() {
        // `SetNameView` を削除
        currentSetNameView?.removeFromSuperview()
        currentSetNameView = nil
    }
}

extension WebViewController: WKNavigationDelegate {
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // ページのタイトルを取得して表示する
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
            self.titleLabel.text = webView.title
        }
    }
    // alertを処理するためのデリゲートメソッド
    public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
            completionHandler()
        }))
        self.present(alertController, animated: true, completion: nil)
    }
    
}
