//
//  EcaTask.swift
//  Sailassist
//
//  Created by 三浦薫巳 on 2023/11/10.
//

import Foundation
import CoreLocation

class EcaTask: Operation {
    enum OperationError: Error {
        case cancelled
    }

    // URLSessionのバックグラウンド実行用の識別子
    private let identifier: String = "get_articles_operation"

    private var req_url: URL
    private var dataTask: URLSessionDataTask? = nil
    private var titles: [String] = []

    // 処理結果を格納する変数
    var result: Result<[String], Error>? = nil

    init(url: URL) {
        self.req_url = url
    }

    // 非同期処理を行う場合、isAsynchronousをオーバーライドしてtrueを返すようにする
    override var isAsynchronous: Bool {
        return true
    }

    // 非同期処理を行う場合、isExecutingのオーバーライドが必要
    // 値を変更するときはKVOの変更通知を行う
    private var _isExecuting: Bool = false
    override var isExecuting: Bool {
        get {
            _isExecuting
        }
        set {
            willChangeValue(forKey: #keyPath(isExecuting))
            _isExecuting = newValue
            didChangeValue(forKey: #keyPath(isExecuting))
        }
    }

    // 非同期処理を行う場合、isFinishedのオーバーライドが必要
    // 値を変更するときはKVOの変更通知を行う
    private var _isFinished: Bool = false
    override var isFinished: Bool {
        get {
            _isFinished
        }
        set {
            willChangeValue(forKey: #keyPath(isFinished))
            _isFinished = newValue
            didChangeValue(forKey: #keyPath(isFinished))
        }
    }

    // キャンセル処理
    override func cancel() {
        super.cancel()

        if let task = dataTask {
            task.cancel()
        }
    }

    // 非同期オペレーションのエントリーポイント
    override func start() {

        // 実行中フラグON
        isExecuting = true

        if isCancelled {
            completionHandler(result: .failure(OperationError.cancelled))
            return
        }

        // バックグラウンド用セッションの作成
        let configuration = URLSessionConfiguration.background(withIdentifier: identifier)
        configuration.isDiscretionary = false

        let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)

        let login = ReqLogin(Id: Preferences.ShipId, Password: Preferences.ShipPassword)
        if let postdata = toJSON(login) {
            print(debug: "タスクの実行:EcaTask 1")
            // RSS XML取得
            var req = URLRequest(url: req_url)
            req.httpMethod = "POST"
            req.addValue("application/json", forHTTPHeaderField: "Content-Type")
            req.httpBody = postdata
            req.timeoutInterval = 20

            dataTask = session.dataTask(with: req)
            dataTask!.resume()
        }
        else {

            return
        }

    }

    // JSON 文字列に変換
    func toJSON<T>(_ reqparam : T) -> Data! where T : Encodable {
        let Jencoder = JSONEncoder()
        var postdata : Data!
        do {
            postdata = try Jencoder.encode(reqparam)
        } catch {
            return nil
        }
        return postdata
    }

    // 処理完了ハンドラ
    private func completionHandler(result: Result<[String], Error>) {
        guard isExecuting else {
            return
        }

        // 実行中フラグOFF
        isExecuting = false

        self.result = result
        self.dataTask = nil

        // 終了フラグON
        isFinished = true
    }
}

extension EcaTask: URLSessionDelegate, URLSessionDataDelegate {

    // データ受信完了
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        print(debug: "タスクの実行:EcaTask 2")
        if isCancelled {
            completionHandler(result: .failure(OperationError.cancelled))
            return
        }

        let xml = String(data: data, encoding: .utf8)!

        do {
            var titles: [String] = []

            // 正規表現でタイトル抽出
            let pattern = "<title>([^<]+)</title>"
            let regex = try NSRegularExpression(pattern: pattern, options: [
                .anchorsMatchLines, .dotMatchesLineSeparators
            ])
            let range = NSRange(location: 0, length: xml.count)
            let results = regex.matches(in: xml, options: [], range: range)

            for result in results {
                let start = xml.index(xml.startIndex, offsetBy: result.range(at: 1).location)
                let end = xml.index(start, offsetBy: result.range(at: 1).length)
                let text = String(xml[start..<end])

                titles.append(text)
            }

            // 1行目はRSSのタイトルなので落とす
            if !titles.isEmpty {
                titles.remove(at: 0)
            }

            self.titles = titles
            print(debug: "タスクの実行:EcaTask 3")
            SharingData.My.location?.latitude = 35.0
            SharingData.My.location?.longitude = 135.0
            var distance = 0.0
            if let nowlocation = SharingData.My.location {
                distance = LocationCalculation.checkPolyline(objPos: iceland, shipPos: nowlocation)
            }
            print(debug: "called: \(distance) \n")
        }
        catch {
            // No Action
        }
    }

    // タスク完了
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {

        if isCancelled {
            completionHandler(result: .failure(OperationError.cancelled))
            return
        }

        if let error = error {
            self.completionHandler(result: .failure(error))
        }
        else {
            self.completionHandler(result: .success(titles))
        }
    }
}

//    var sharingData = SharingData.shared
//
//    override func main() {
//        print(debug: "タスクの実行:EcaTask 1")
//        let login = ReqLogin(Id: Preferences.ShipId, Password: Preferences.ShipPassword)
//        let sessionLogin = SessionLogin.OnlyOne
//        sessionLogin.RequestLogin(login)
//    }


//    private func checkEca() {
//        print(debug: "タスクの実行:EcaTask3")
//        let ecaArea = sharingData.ecaArea.map{ $0.1 }.filter{ $0.isRunning == true }
////        if let ecaArea = ecaArea[0] {
////            print(debug: "called")
//        var distance = 0.0
//            if let nowlocation = SharingData.My.location {
//                distance = LocationCalculation.checkPolyline(objPos: iceland, shipPos: nowlocation)
//            }
//        print(distance)
////        }
//    }

//    override func main() {
//        print(debug: "タスクの実行(eca)")
//        print("this operation refresh id is \(self.id)")
//        let location = SharingData.My.location
//
//        let ecaArea = sharingData.ecaArea.map{ $0.1 }.filter{ $0.isRunning == true }
//        if let ecaArea = ecaArea.first {
//            print(debug: ecaArea)
//        }
//    }
//    override func main() {
//        print(debug: "called eca task")

//        let ecaArea = sharingData.ecaArea.map{ $0.1 }.filter{ $0.isRunning == true }
//        if let ecaArea = ecaArea.first {
//            var points: [CLLocationCoordinate2D] = []
//            points = ecaArea.first?.points
//            let distance = LocationCalculation.checkPolyline(objPos: points, shipPos: location)
//        }

//        @Published var isRunning: Bool = false     //ECA実行中
//        @Published var name: String = ""           //ECA名称
//        @Published var swNotice: UInt32 = 6        //ECA通知[NM]
//        @Published var swStart: UInt32 = 5         //ECA開始[NM]
//        @Published var swFinish: UInt32 = 4        //ECA終了[NM]
//    }
//}
