//
// 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,
    //              //							])
    //            }
    //          }
    //        })
    //      }
    //    }
  }
}
