//
//  ServerSession.swift
//  forShip
//
//  Created by Mamoru Sugita on 2023/10/25.
//

import Foundation

typealias SessionResponse = Result<Data, APIError>

class ServerSession{

    /// 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
    }

    /// JSON 文字列から変換
    func fromJSON<T>(resultData: Data, resltType : T.Type ) -> T! where T : Decodable {
        do{
            let decoder = JSONDecoder()
            let resjson : T = try decoder.decode(resltType.self, from: resultData)
            return resjson
        } catch {
            let jsonstr = String(data: resultData, encoding: .utf8)!
            print(debug: "\(jsonstr)")
            return nil
        }
    }

    func postJson(_ req_url : URL, _ postdata : Data, completion: @escaping (SessionResponse) -> Void){
        var req = URLRequest(url: req_url)
        req.httpMethod = "POST"
        req.addValue("application/json", forHTTPHeaderField: "Content-Type")
        req.httpBody = postdata
        req.timeoutInterval = 20     // タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更

        // サーバー送信
        let session = URLSession(configuration: .default, delegate: nil, delegateQueue: OperationQueue.main)

        session.dataTask(with: req, completionHandler: {(data, response, error ) in
            session.finishTasksAndInvalidate()

            do{
                if error != nil{
                    throw APIError.clientError
                }
                guard let indata = data, let inresponse = response as? HTTPURLResponse else {
                    throw APIError.responseError
                }
                if inresponse.statusCode != 200 {
                    throw APIError.serverError
                }
                //Cookieを保存
                if let fields = inresponse.allHeaderFields as? [String: String], let url = inresponse.url {
                    for cookie in HTTPCookie.cookies(withResponseHeaderFields: fields, for: url) {
                        HTTPCookieStorage.shared.setCookie(cookie)
                    }
                }
                DispatchQueue.main.async {
                    completion(.success(indata))
                }
            }catch{
                if error as? APIError != nil{
                    completion(.failure(error as! APIError))
                }
                else{
                    completion(.failure(.unknown))
                }
            }
        }).resume()
    }

    func getJson(_ req_url : URL, completion: @escaping (SessionResponse) -> Void){

        var req = URLRequest(url: req_url)
        req.addValue("application/json", forHTTPHeaderField: "Content-Type")
        req.timeoutInterval = 20     // タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更

        // サーバー送信
        let session = URLSession(configuration: .default, delegate: nil, delegateQueue: OperationQueue.main)

        session.dataTask(with: req, completionHandler: {(data, response, error ) in
            session.finishTasksAndInvalidate()

            do{
                if error != nil{
                    throw APIError.clientError
                }
                guard let indata = data, let inresponse = response as? HTTPURLResponse else {
                    throw APIError.responseError
                }
                if inresponse.statusCode != 200 {
                    throw APIError.serverError
                }
                DispatchQueue.main.async {
                    completion(.success(indata))
                }
            }catch{
                if error as? APIError != nil{
                    completion(.failure(error as! APIError))
                }
                else{
                    completion(.failure(.unknown))
                }
            }
        }).resume()
    }

    func deleteJson(_ req_url : URL, completion: @escaping (SessionResponse) -> Void){

        var req = URLRequest(url: req_url)
        req.httpMethod = "DELETE"
        req.addValue("application/json", forHTTPHeaderField: "Content-Type")
        req.timeoutInterval = 20     // タイムアウト3秒 → Amedasでタイムアウトエラー20秒に変更

        // サーバー送信
        let session = URLSession(configuration: .default, delegate: nil, delegateQueue: OperationQueue.main)

        session.dataTask(with: req, completionHandler: {(data, response, error ) in
            session.finishTasksAndInvalidate()

            do{
                if error != nil{
                    _ = APIError.clientError
                    throw APIError.clientError
                }
                guard let indata = data, let inresponse = response as? HTTPURLResponse else {
                    throw APIError.responseError
                }
                if inresponse.statusCode != 200 {
                    throw APIError.serverError
                }
                DispatchQueue.main.async {
                    completion(.success(indata))
                }
            }catch{
                if error as? APIError != nil{
                    completion(.failure(error as! APIError))
                }
                else{
                    completion(.failure(.unknown))
                }
            }
        }).resume()
    }

    // HTTPCookieStorageに特定のCookieが保存されているかを調べる
    func isCookieSet(name: String, url: URL) -> Bool {
        if let cookies = HTTPCookieStorage.shared.cookies(for: url) {
            for cookie in cookies {
                if (cookie.name == name) {
                    return true
                }
            }
        }
        return false
    }
}
