//
//  XPSDKResponse.swift
//  XProtect
//
//  Created by Ivelin Tsankov on 1/18/17.
//  Copyright © 2017 Milestone Systems A/S. All rights reserved.
//

import Foundation

@objc open class XPSDKResponse: NSDictionary {
    var request: XPSDKRequest?
    open internal(set) var response: NSDictionary?
    open internal(set) var isResponse = false
    open internal(set) var isProcessing = false
    open internal(set) var items: NSDictionary?
    open internal(set) var parameters: NSDictionary?
    open internal(set) var subItems: NSArray?
    open internal(set) var sequences: NSDictionary?
    open internal(set) var exports: NSDictionary?
    open internal(set) var notification: NSDictionary?
    open internal(set) var outputsAndEvents: NSArray?
    open internal(set) var users: NSArray?
    open internal(set) var error: NSError?
    open internal(set) var responseItems: NSArray?
    
    internal convenience init(forRequest request: XPSDKRequest, response: NSDictionary) {
        self.init()
        
        log.info(response)
        
        self.response = response
        self.request = request
        
        let communication = response[XPSDKCommunication] as? NSDictionary
        
        if communication == nil {
            return
        }
        
        var com = communication![XPSDKCommand]
            
        if com == nil {
            if communication![XPSDKEncryptedCommand] != nil {
                let encryptedCommand = communication![XPSDKEncryptedCommand] as! NSDictionary
                let encryptedCommandValue = encryptedCommand[XPSDKvalue] as! String
                
                let dencryptedCommand = XPSDKConnection.sharedConnection.dhe?.decrypt(encryptedCommandValue)
                
                do {
                    let xmlParse = try KPXMLParser.dictionary(forXMLData: dencryptedCommand?.data(using: String.Encoding.unicode))
                    
                    com = xmlParse[XPSDKCommand] as! NSDictionary
                } catch _ {
                    return
                }
            }
        }
        
        let command = com as? NSDictionary
        
        var commandName: String?
        if let commandNameDict = command?[XPSDKName] as? NSDictionary {
            commandName = commandNameDict[XPSDKvalue] as? String
            if commandName == nil {
                return
            }
        }
        
        let commandTypeDict = command?[XPSDKType] as! NSDictionary
        let commandType = commandTypeDict[XPSDKvalue]
        
        self.isResponse = ((commandType as AnyObject).isEqual(to: XPSDKResponseKey))
        self.isProcessing = ((commandType as AnyObject).isEqual(to: XPSDKProcessing))
        
        // Output parameters
        let outputParams = command?[XPSDKOutputParams] as? NSDictionary
        
        var data: AnyObject?
        
        if outputParams != nil {
            data = outputParams![XPSDKParam] as AnyObject
        
            var params: NSArray? = nil
            if data is NSDictionary {
                params = [data!]
            } else {
                params = data as? NSArray
            }
            
            let values = NSMutableDictionary()
            
            if params != nil {
                for param in params! {
                    var p = param as? NSDictionary
                    var valueString = p?[XPSDKValue]
                    if valueString == nil {
                        valueString = ""
                    }
                    
                    let paramName = p?[XPSDKName] as! String
                    values[paramName] = valueString
                }
                
                self.parameters = values
            }
        }
            
        // Sub-items
        if let data = command?[XPSDKSubItems] as? NSDictionary {
            let object = data[XPSDKItem]
                if object is NSDictionary {
                    self.subItems = [object!]
                } else {
                    self.subItems = object as? NSArray
                }
        }
        
        // Sequences
        self.sequences = command?[XPSDKSequences] as? NSDictionary
        
        // Outputs and events
        data = command?[XPSDKOEHeaderGroup] as AnyObject?
        
        if data is NSDictionary {
            self.outputsAndEvents = [data!]
        } else {
            self.outputsAndEvents = data as? NSArray
        }
        
        // Exports
        self.exports = command?[XPSDKExports] as? NSDictionary
        
        // Response items
        var items: NSArray?

        if let XPSDKItems = command?[XPSDKItems] as? NSDictionary {
            if let data = XPSDKItems[XPSDKItem] {
                if data is NSDictionary {
                    self.responseItems = [data]
                } else {
                    self.responseItems = data as? NSArray
                }
            }
        }
        
        // Items
        if commandName == XPSDKGetAllViewsAndCameras {
            self.items = self.responseItems?.firstObject as! NSDictionary
//            if items != nil {
//                self.items = self.processItems(items!)
//            }
        } else if commandName == XPSDKGetPermittedUsers {
             // Users
            self.users = items
        } else if commandName == XPSDKLiveMessage {
            // Notifications from LiveMessage
            if let notification = data as? NSDictionary {
                let notificationType = notification[XPSDKType] as! String
                
                if notificationType == XPSDKNotification {
                    self.notification = notification
                }
            }
        }
        
        var result = (command?[XPSDKResult] as! NSDictionary)[XPSDKvalue] as! String
        
        result = result.replacingOccurrences(of: "\n", with: "") // remove /n from result
        result = result.trimmingCharacters(in: CharacterSet.whitespaces) // remove whitespace for result
        
        if result != XPSDKOK {
            var errorText = ""
            if let commandErrorString = command?[XPSDKErrorString] as? NSDictionary {
                errorText = commandErrorString[XPSDKvalue] as! String
            }
            
            var errorCodeValue = -1
            if let errorCode = command?[XPSDKErrorCode] as? NSDictionary {
                errorCodeValue = Int((errorCode[XPSDKvalue] as! String))!
            }
            let error = [errorText: NSLocalizedDescriptionKey]
            self.error = NSError(domain: XPSDKResponseErrorDomain, code: errorCodeValue, userInfo: error)
        }
    }
    
    fileprivate func processItems(_ items: NSArray) -> NSDictionary {
        let result = NSMutableDictionary()
        self.processItems(items, toDictionary: result)
        
        return result
    }
    
    fileprivate func processItems(_ items: NSArray, toDictionary dictionary: NSMutableDictionary) {
        for i in items {
            let item = i as! NSDictionary
            let itemType = item[XPSDKType] as? String
            let itemGroup = NSMutableString()
            itemGroup.appendFormat("%@s", itemType!)

            if dictionary[itemGroup] == nil {
                dictionary[itemGroup] = NSMutableDictionary()
            }
            
            let i = item[XPSDKItems] as! NSDictionary
            let object = i[XPSDKItem]
            
            var subItems: NSArray?
            
            if object is NSDictionary {
                subItems = NSArray(object: object!)
            } else {
                subItems = object as? NSArray
            }
            
            var itemItem: NSDictionary? = item[XPSDKItems] as? NSDictionary
            if itemItem != nil {
                itemItem = nil
            }
            
            let dictionaryItemGroup = dictionary[itemGroup] as! NSDictionary
            if let itemID = item[XPSDKId] as? String {
                if var id = dictionaryItemGroup[itemID] {
                    id = item
                }
            }
            
            if subItems != nil {
                for si in subItems! {
                    let subItem = si as! NSDictionary
                    let subItemType = subItem[XPSDKItem] as? String
                    let subItemGroup = NSMutableString()
                    subItemGroup.appendFormat("%@s", subItemType!)
                    
                    var itemSubItemGroup = item[subItemGroup]
                    if itemSubItemGroup == nil {
                        itemSubItemGroup = NSMutableArray()
                    }
                    
                    (itemSubItemGroup! as AnyObject).add(subItem[XPSDKId])
                }

                self.processItems(subItems!, toDictionary: dictionary)
            }
        }
    }
    
    func getItemsWithType(_ type: String) -> NSArray? {
        let predicate = NSPredicate { (item: Any?, bindings: [String: Any]?) -> Bool in
            
            return (item as! NSDictionary)["Type"] as! String == type
        }
        
        if self.responseItems == nil {
            return nil
        }
        
        return (self.responseItems?.filtered(using: predicate))! as NSArray?
    }
    
    open func endpoints() -> NSArray? {
        var endpoints = self.getItemsWithType("Endpoint")
        
        if endpoints == nil {
            return nil
        }
        
        if endpoints!.count > 0 {
            let epzero = endpoints![0] as! NSDictionary
            
            if epzero["Folder"] as! String == "Yes" {
                
                var epzeroAnyObject: AnyObject?
                epzeroAnyObject = (epzero["Items"] as! NSDictionary)["Item"] as AnyObject
                
                if epzeroAnyObject is NSArray {
                    endpoints = epzeroAnyObject as? NSArray
                } else {
                    endpoints = [epzeroAnyObject!]
                }
            }
        }
    
        return endpoints!;
    }
    
    open func alarms() -> NSArray? {
        return self.getItemsWithType(XPSDKAlarm)
    }

    open func alarmDataSettings() -> NSArray? {
        return self.getItemsWithType(XPSDKAlarmDataSetting)
    }
}
