//
// Created by Alexander Zalutskiy on 10.08.15.
// Copyright (c) 2015 Alexandr Zalutskiy. All rights reserved.
//

import Foundation
import XCGLogger

let FacadeLoginError = "FacadeLoginError"
let FacadeLoginSuccess = "FacadeLoginSuccess"
let FacadeUserNeedAuth = "FacadeUserNeedAuth"
let FacadeUserNeedAuthError = NSError(domain: "telecom.kz", code: -1000, userInfo: nil)
let TokenExpiredNotification = "TokentExpired"

class CustomConnectionDelegate: NSObject, NSURLConnectionDataDelegate {
    var onFinish: (() -> Void)!
    var onError: ((NSError) -> Void)!
    var onSuccess: (() -> Void)!
    static var randomToken: String = ""
    var login: String = ""
    var password: String = ""
    var loginType: Facade.LoginType!
    static var counter = 0
    
    override init() {
        
    }
    
    func connection(connection: NSURLConnection, didFailWithError error: NSError) {
        //    let error = NSError(domain: "kz.telecom", code: 0, userInfo: [
        //      NSLocalizedDescriptionKey: §"login.error.incorrect_login_or_password",
        //      ])
        
        Router.globalLog.error(error.debugDescription)
        self.onError(error)
    }
    
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        print(response)
        Router.globalLog.debug(response)
        guard CustomConnectionDelegate.counter == 1 else { return }
        self.onFinish()
        if let responseUrl = response.URL where responseUrl.host == "www.google.kz" {
            let params = [
                Facade.LoginParamsKeys.ThirdStepClientId: CustomConnectionDelegate.randomToken
            ]
            let r = request(.POST, Facade.LoginUrls.ThirdStep, parameters: params, encoding: .JSON)
            let customDel = CustomConnectionDelegate()
            customDel.onError = onError
            customDel.onFinish = onFinish
            customDel.onSuccess = onSuccess
            customDel.login = login
            customDel.password = password
            customDel.loginType = loginType
            CustomConnectionDelegate.counter += 1
            let con = NSURLConnection(request: r.request!, delegate: customDel)
            con!.start()
        } else {
            let error = NSError(domain: "kz.telecom", code: 0, userInfo: [
                NSLocalizedDescriptionKey: §"login.error.incorrect_login_or_password",
                ])
            self.onError(error)
        }
    }
    
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
        switch CustomConnectionDelegate.counter {
        case 0:
            onFinish()
            
            let url = NSURL(string: Facade.LoginUrls.SecondStep)!
            var mutableRequest = NSMutableURLRequest(URL: url)
            mutableRequest.HTTPMethod = Method.GET.rawValue
            
            var params = Facade.LoginParams.SecondStep
            params[Facade.LoginParamsKeys.ClientIdKey] = CustomConnectionDelegate.randomToken
            
            mutableRequest = ParameterEncoding.URL.encode(mutableRequest, parameters: params).0
            
            var userParams = Facade.LoginParams.SecondStepBody
            userParams[Facade.LoginParamsKeys.BodyAuthType] = loginType.rawValue
            userParams[Facade.LoginParamsKeys.BodyUsername] = login
            userParams[Facade.LoginParamsKeys.BodyPassword] = password
            
            mutableRequest.HTTPMethod = Method.POST.rawValue
            mutableRequest = ParameterEncoding.URL.encode(mutableRequest, parameters: userParams).0
            
            let r = request(mutableRequest)
            let customDel = CustomConnectionDelegate()
            customDel.onError = onError
            customDel.onFinish = onFinish
            customDel.onSuccess = onSuccess
            customDel.login = login
            customDel.password = password
            customDel.loginType = loginType
            
            CustomConnectionDelegate.counter += 1
            let con = NSURLConnection(request: r.request!, delegate: customDel)
            con!.start()
            
            break
        case 2:
            self.onFinish()
            let json = JSON(data: data)
            if let errorCode = json["error_code"].int {
                // Success login
                if errorCode == 0 {
                    //                      let access_token = json["access_token"] as! String
                    //                      let client_id = randomToken
                    Facade.expiresIn = json["expires_in"].doubleValue
                    Facade.accessToken = json["access_token"].stringValue
                    Facade.clientId = CustomConnectionDelegate.randomToken
                    //											Facade.clientId = json["client_id"] as? String
                    //											self.notificationCenter.postNotificationName(FacadeLoginSuccess, object: self)
                    UserManager.sharedInstance().login = self.login
                    UserManager.sharedInstance().password = self.password
                    self.onSuccess()
                } else {
                    let error = NSError(domain: "kz.telecom", code: 0, userInfo: [
                        NSLocalizedDescriptionKey: json["error"].stringValue,
                        ])
                    self.onError(error)
                    //											self.notificationCenter.postNotificationName(FacadeLoginError, object: self, userInfo: [
                    //												FacadeNotificationErrorKey: error,
                    //											])
                }
                break
            }
            
            // Error login or password
            
            //      CustomConnectionDelegate.counter += 1
            break
        default:
            break
        }
        
    }
    
    func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool {
        return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
    }
    
    func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            //      if challenge.protectionSpace.host.containsString("cabinet.idport.kz") {
            challenge.sender?.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!), forAuthenticationChallenge: challenge)
            
            challenge.sender?.continueWithoutCredentialForAuthenticationChallenge(challenge)
            //      }
        }
    }
}

extension Facade {
    var UserNeedAuthNotification: NSNotification {
        return NSNotification(name: FacadeUserNeedAuth, object: self,
                              userInfo: [FacadeNotificationErrorKey: FacadeUserNeedAuthError])
    }
    //  randomToken
    //  loginType.rawValue
    //  login
    //  password
    static var phoneNumber: String? = nil
    static var accessToken: String? = nil
    static var clientId: String? = nil
    static var expiresIn: NSTimeInterval? = nil {
        didSet {
            guard let expiresIn = expiresIn else {
                return
            }
            let seconds = Double(NSDate(timeIntervalSince1970: expiresIn).secondsFrom(NSDate()))
            let delay = seconds * Double(NSEC_PER_SEC)
            let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
            dispatch_after(time, dispatch_get_main_queue(), {() in
                if self.expiresIn != nil {
                    NSNotificationCenter.defaultCenter().postNotificationName(TokenExpiredNotification, object: nil)
                }
            })
        }
    }
    
    struct LoginUrls {
        static let FirstStep = "https://cabinet.idport.kz:8443/IdPort/oauth/"
        static let SecondStep = "https://cabinet.idport.kz:8443/IdPort/oauth/process.cfm"
        static let ThirdStep = "https://telecom.kz/api/account/get_token.json"
    }
    
    struct LoginParams {
        // Apend IN_CLIENT_ID before sending
        static let FirstStep: [String: AnyObject] = [
            "IN_SYSTEM_PROVIDER_CODE": "KAZNET",
            "IN_URL_REDIRECT": "https://www.google.kz",
            "IN_URL_TOKEN": "http://telecom.kz/auth20/save_access_token",
            ]
        
        // Apend IN_CLIENT_ID before sending
        static let SecondStep: [String: AnyObject] = [
            "IN_SYSTEM_PROVIDER_CODE": "KAZNET",
            "IN_URL_REDIRECT": "https://www.google.kz",
            "IN_URL_TOKEN": "http://telecom.kz/auth20/save_access_token",
            "isProvider": 0,
            ]
        
        static let SecondStepBody: [String: AnyObject] = [
            "sSubmit": "ВХОД В КАБИНЕТ",
            ]
    }
    
    struct LoginParamsKeys {
        static let ClientIdKey = "IN_CLIENT_ID"
        static let BodyAuthType = "AuthType"
        static let BodyUsername = "j_username"
        static let BodyPassword = "j_password"
        static let ThirdStepClientId = "client_id"
    }
    
    enum LoginType: Int {
        case Login = 1
        case PhoneNumber = 2
    }
    
    func login(login: String, password: String, loginType: LoginType, onSuccess: () -> Void, onError: (error: NSError) -> Void, onFinish: () -> Void) {
        CustomConnectionDelegate.counter = 0
        let cookiesStorage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
        
        if let cookies = cookiesStorage.cookies where cookies.count != 0 {
            for cookie in cookies {
                if cookie.domain.rangeOfString("cabinet.idport.kz") != nil {
                    cookiesStorage.deleteCookie(cookie)
                }
            }
        }
        let uuid = NSUUID().UUIDString
        let randomToken = uuid.stringByReplacingOccurrencesOfString("-", withString: "")
        var params = LoginParams.FirstStep
        params[LoginParamsKeys.ClientIdKey] = randomToken
        
        //	First Step: Simple .GET
        let r = request(.GET, LoginUrls.FirstStep, parameters: params, encoding: .URL)
        let customDel = CustomConnectionDelegate()
        customDel.onError = onError
        customDel.onFinish = onFinish
        CustomConnectionDelegate.randomToken = randomToken
        customDel.onSuccess = onSuccess
        customDel.login = login
        customDel.password = password
        customDel.loginType = loginType
        
        let con = NSURLConnection(request: r.request!, delegate: customDel)
        con!.start()
        
        Router.globalLog.debug("loginRequestStarted")
        
        //		print(r.cURLRepresentation())
        //    r.responseData { (resp) in
        //      onFinish()
        //      switch resp.result {
        //      // Error on sending data
        //      case .Failure(let error):
        //        onError(error: error)
        //        //				self.notificationCenter.postNotificationName(FacadeLoginError, object: self, userInfo: [
        //        //						FacadeNotificationErrorKey: error
        //        //				])
        //        break
        //      // Second Step: OAuth on iDPort
        //      case .Success:
        //        let url = NSURL(string: LoginUrls.SecondStep)!
        //        var mutableRequest = NSMutableURLRequest(URL: url)
        //        mutableRequest.HTTPMethod = Method.GET.rawValue
        //
        //        var params = LoginParams.SecondStep
        //        params[LoginParamsKeys.ClientIdKey] = randomToken
        //
        //        mutableRequest = ParameterEncoding.URL.encode(mutableRequest, parameters: params).0
        //
        //        var userParams = LoginParams.SecondStepBody
        //        userParams[LoginParamsKeys.BodyAuthType] = loginType.rawValue
        //        userParams[LoginParamsKeys.BodyUsername] = login
        //        userParams[LoginParamsKeys.BodyPassword] = password
        //
        //        mutableRequest.HTTPMethod = Method.POST.rawValue
        //        mutableRequest = ParameterEncoding.URL.encode(mutableRequest, parameters: userParams).0
        //
        //        let r = request(mutableRequest)
        //        //				print(r.cURLRepresentation())
        //        r.responseData(completionHandler: { (resp) in
        //          onFinish()
        //          switch resp.result {
        //          // Error in sending on Second Step
        //          case .Failure(let error):
        //            //						self.notificationCenter.postNotificationName(FacadeLoginError, object: self,
        //            //								userInfo: [
        //            //										FacadeNotificationErrorKey: error
        //            //								]
        //            //						)
        //            onError(error: error)
        //            break
        //          case .Success:
        //            // If Second Step success
        //            if let responseUrl = resp.response?.URL where responseUrl.host == "www.google.kz" {
        //              let params = [
        //                LoginParamsKeys.ThirdStepClientId: randomToken
        //              ]
        //              let r = request(.POST, LoginUrls.ThirdStep, parameters: params, encoding: .JSON)
        //              //							print(r.cURLRepresentation())
        //              r.responseJSON(completionHandler: { (resp) in
        //                onFinish()
        //                switch resp.result {
        //                case .Failure(let error):
        //                  //									self.notificationCenter.postNotificationName(FacadeLoginError, object: self,
        //                  //											userInfo: [
        //                  //													FacadeNotificationErrorKey: error
        //                  //											]
        //                  //									)
        //                  onError(error: error)
        //                  break
        //                case .Success(let json):
        //                  if let errorCode = json["error_code"] as? Int {
        //                    // Success login
        //                    if errorCode == 0 {
        //                      //                      let access_token = json["access_token"] as! String
        //                      //                      let client_id = randomToken
        //                      Facade.expiresIn = json["expires_in"] as! Double
        //                      Facade.accessToken = json["access_token"] as? String
        //                      Facade.clientId = randomToken
        //                      //											Facade.clientId = json["client_id"] as? String
        //                      //											self.notificationCenter.postNotificationName(FacadeLoginSuccess, object: self)
        //                      UserManager.sharedInstance().login = login
        //                      UserManager.sharedInstance().password = password
        //                      onSuccess()
        //                    } else {
        //                      let error = NSError(domain: "kz.telecom", code: 0, userInfo: [
        //                        NSLocalizedDescriptionKey: json["error"] as! String,
        //                        ])
        //                      onError(error: error)
        //                      //											self.notificationCenter.postNotificationName(FacadeLoginError, object: self, userInfo: [
        //                      //												FacadeNotificationErrorKey: error,
        //                      //											])
        //                    }
        //                    break
        //                  }
        //                }
        //                // Error login or password
        //              })
        //            } else {
        //              let error = NSError(domain: "kz.telecom", code: 0, userInfo: [
        //                NSLocalizedDescriptionKey: §"login.error.incorrect_login_or_password",
        //                ])
        //              onError(error: error)
        //              //							self.notificationCenter.postNotificationName(FacadeLoginError, object: self, userInfo: [
        //              //								FacadeNotificationErrorKey: error,
        //              //							])
        //            }
        //          }
        //        })
        //      }
        //    }
    }
}
