//
//  SemesterScoreDAL.swift
//  SemesterScore
//
//  Created by Yao Ming Huang on 2017/11/15.
//  Copyright © 2017年 ChunTai Chen. All rights reserved.
//

import Foundation
import React
import ischoolFramework
import RxSwift
import AEXML

@objc(DSAServices)
class DSAServices:NSObject{

    // 因為 react native 每次都會重建，所以不會有登出之後快取到前一個使用者的連線。
    private var contracts: [String: Connection] = [:]

    @objc func call(_ contract: String, _ serviceName: String,_ body: String, _ callback: @escaping RCTResponseSenderBlock) -> Void {

        guard let dsns = Module.instance.current?.dsns else {
            callback(["<error><message>無法取得 dsns 位置，是否未選擇模組？？？</message></error>", NSNull()])
            return
        }

        let pupa = Pupa.getInsance()
        let scope = "\(dsns):\(contract)"
        let SELF = self
        
        let _  = Observable.of(scope)
            .flatMap { (scope) -> Observable<Connection> in // 取得 Connection 物件。
                if let objContract = SELF.contracts[scope] {
                    return Observable.of(objContract) // 從 cache 拿 Connection
                } else {
                    return pupa.getToken(scopes: scope) // 依 scope 取得 OAuthTokenManaged。
                        .concatMap { (tokenManaged) -> Observable<Connection> in
                            return Connection().connect(dsns: dsns, contract: contract, token: tokenManaged) // 建立新 Connection。
                        }
                        .do (onNext: { conn in // connect 沒炸掉才會到這裡。
                            SELF.contracts[scope] = conn // 快取 Connection。
                        })
                }
            }
            .flatMap({ (conn) -> Observable<AEXMLElement> in // 呼叫 Service 取得 Response。
                return conn.sendRequest(service: serviceName, bodyContent: body)
            })
            .map { $0.xmlString } // AEXMLElement 轉為 String。
            .subscribe(onNext: { rspstr in
                callback([NSNull(), rspstr])
            }, onError: {err in

                guard let error = err as? PupaError else {
                    callback(["<error><message>發生了工程師沒想到的錯誤。</message></error>", NSNull()])
                    return
                }

                switch error {
                case let .DSAService(dsns, code, service, reason, request, response):
                    callback(["<error><code>\(code)</code><message>\(reason)</message>\(request ?? "")\(response ?? "")</error>", NSNull()])
                    print(dsns, code, service, reason, request ?? "", response ?? "")
                default:
                    callback(["<error><message>發生了工程師沒想到的錯誤。</message></error>", NSNull()])
                    print(error)
                }
            })
    }
}
