//
//  WebserviceClient.swift
//  ipbc-Client
//
//  Created by Gerrit Linnemann on 09.09.15.
//  Copyright (c) 2015 Adawim UG (haftungsbeschränkt). All rights reserved.
//

import Foundation
import Alamofire


private let x_SomeManagerSharedInstance = WebserviceClient()

class WebserviceClient {
    
    private var isNetworkAvailable : Bool = false
    private var isNetworkAvailableFirstCheck : Bool = true
    
    class var sharedInstance: WebserviceClient {
        return x_SomeManagerSharedInstance
    }
    
    init() {
        self.initNetwork()
        self.initTimer()
        self.initOnNotification()
    }
    
    // MARK: init-functions
    
    private func initNetwork() {
        self.checkNetwork()
    }
    
    private func initTimer() {
        NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: Selector("checkForNewIPTimerAction:"), userInfo: nil, repeats: true)
    }
    
    private func initOnNotification() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "observeUserIPHasChanged", name: Constants.Notification.NF_IP_HAS_CHANGED, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "observeUserDataHasChanged", name: Constants.Notification.NF_DATA_USERDATA_HAS_CHANGED, object: nil)
    }
    
    // MARK: Network
    
    internal func checkNetwork() {
        let networkLastState : Bool = false
        
        Alamofire.request(.GET, Constants.WebService.GET_USERS_IP, parameters: nil)
            .validate(statusCode: 200..<201)
            .validate(contentType: ["text/plain"])
            .responseString { response in
                /*
                print(response.request)  // original URL request
                print(response.response) // URL response
                print(response.data)     // server data
                print(response.result)   // result of response serialization
                */
                
                switch response.result {
                case .Success:
                    self.isNetworkAvailable = true
                    let newIP : String = response.result.value ?? ""
                    print("WebserviceClient: Network available from IP \(newIP)")
                    self.detectIP()
                case .Failure(let error):
                    self.isNetworkAvailable = false
                    print("WebserviceClient: Error during network-check:")
                    print(error)
                }
                
                if self.isNetworkAvailableFirstCheck || self.isNetworkAvailable != networkLastState {
                    if self.isNetworkAvailable {
                        NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notification.NF_NETWORK_AVAILABLE, object: nil)
                    } else {
                        NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notification.NF_NETWORK_NOT_AVAILABLE, object: nil)
                    }
                }
                
                if self.isNetworkAvailableFirstCheck && self.isNetworkAvailable {
                    self.thingsToDoOnNetworkAvailableRightAfterStart()
                }
                
                self.isNetworkAvailableFirstCheck = false
        }
    }
    
    private func thingsToDoOnNetworkAvailableRightAfterStart() {
        self.doUpdate()
        //self.detectMasterDomains()
    }
    
    private func detectIP() {
        Alamofire.request(.GET, Constants.WebService.GET_USERS_IP, parameters: nil)
            .validate(statusCode: 200..<201)
            .validate(contentType: ["text/plain"])
            .responseString { response in
                /*
                print(response.request)  // original URL request
                print(response.response) // URL response
                print(response.data)     // server data
                print(response.result)   // result of response serialization
                */

                switch response.result {
                case .Success:
                    let defaults = NSUserDefaults.standardUserDefaults()
                    let newIP : String = response.result.value ?? ""
                    let oldIP : String = defaults.stringForKey(Constants.UserDefaults.PERSIST_LAST_USERS_IP) ?? ""

                    //print("WebserviceClient: compare old IP \(oldIP) with new IP \(newIP)")
                    if oldIP != newIP {
                        // IP has changed

                        defaults.setValue(newIP, forKey: Constants.UserDefaults.PERSIST_LAST_USERS_IP)
                        print("WebserviceClient: new IP: \(newIP)")

                        NSNotificationCenter.defaultCenter().postNotificationName(Constants.Notification.NF_IP_HAS_CHANGED, object: newIP)
                    }
                case .Failure(let error):
                    print("WebserviceClient: Error during get current IP:")
                    print(error)
                }
        }
    }
    
    private func detectMasterDomains() {
        Alamofire.request(.GET, Constants.WebService.GET_MASTER_DOMAINS, parameters: nil)
            .validate(statusCode: 200..<201)
            .validate(contentType: ["text/plain"])
            .responseJSON { response in
                /*
                print(response.request)  // original URL request
                print(response.response) // URL response
                print(response.data)     // server data
                print(response.result)   // result of response serialization
                */
                
                switch response.result {
                case .Success:
                    if let responseJSON = response.result.value {
                        print("WebserviceClient: MasterDomains: \(responseJSON)")
                        //TODO: implement what to do now
                    }
                case .Failure(let error):
                    print("WebserviceClient: Error during get current IP:")
                    print(error)
                }
        }
    }
    
    // MARK: Timer fire actions
    
    @objc func checkForNewIPTimerAction(timer : NSTimer) {
        self.detectIP()
    }
    
    // MARK: Observer functions
    
    @objc func observeUserIPHasChanged() {
        self.doUpdate()
    }
    
    @objc func observeUserDataHasChanged() {
        self.doUpdate()
    }
    
    private func doUpdate() {
        let domain : String = NSUserDefaults.standardUserDefaults().stringForKey(Constants.UserDefaults.HOST) ?? ""
        let token : String = NSUserDefaults.standardUserDefaults().stringForKey(Constants.UserDefaults.TOKEN) ?? ""
        
        if !domain.isEmpty && !token.isEmpty {
            let headers = [
                "Content-Type": "application/json"
            ]
            /*let parameters = [
                "domain": domain,
                "token": token
            ]*/
            /*let parameters = [
                "": "{\"domain\":\"\(domain)\", \"token\":\"\(token)\"}"
            ]*/
            let parameters : String = toStr([
                "domain": domain,
                "token": token
            ])
            
            Alamofire.request(.POST, Constants.WebService.UPDATE, headers: headers, parameters: [:], encoding: .Custom({
                    (convertible, params) in
                    let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
                    mutableRequest.HTTPBody = parameters.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
                    return (mutableRequest, nil)
                }))
                .validate(statusCode: 200..<201)
                .validate(contentType: ["application/json"])
                .responseString { response in
                    /*
                    print(response.request)  // original URL request
                    print(response.response) // URL response
                    print(response.data)     // server data
                    print(response.result)   // result of response serialization
                    */
                    
                    switch response.result {
                    case .Success:
                        if let responseJSON = response.result.value {
                            print("WebserviceClient: Update response: \(responseJSON)")
                        }
                    case .Failure(let error):
                        print("WebserviceClient: Error during update:")
                        print(error)
                    }
            } // END ALAMOFIRE
            
            
        }   // END IF
    }
    
    // MARK: Getter
    
    func getIP() -> String {
        let defaults = NSUserDefaults.standardUserDefaults()
        if let ip = defaults.stringForKey(Constants.UserDefaults.PERSIST_LAST_USERS_IP) {
            return ip
        } else {
            return ""
        }
    }
    
    func getIsNetworkAvailable() -> Bool {
        return isNetworkAvailable
    }
    
    // MARK: Helper
    
    private func toStr(array : NSDictionary) -> String {
        var string : NSString = ""
        
        do {
            let data = try NSJSONSerialization.dataWithJSONObject(array, options: [])
            string = NSString(data: data, encoding: NSUTF8StringEncoding)!
        } catch {
            
        }
        
        return string as String
    }
}