/*
 *  Copyright © 2016, 2017, Oracle and/or its affiliates. All rights reserved.
 *  This software is dual-licensed to you under the MIT License (MIT) and
 *  the Universal Permissive License (UPL). See the LICENSE file in the root
 *  directory for license terms. You may choose either license, or both.
 */

import UIKit
import EnterpriseLib

class HumidityDeviceMonitorView: UIViewController {
    
    var virtualDevice: VirtualDevice?
    @objc var cvs: [String] = []
    @objc var idx = 0
    
    @IBOutlet var SixthViewOutlet: UIView!
    
    @IBOutlet weak var appNameLabelOutlet: UILabel!
    
    @IBOutlet weak var deviceNameLabelOutlet: UILabel!
    
    @IBOutlet weak var humidityValueLabelOutlet: UILabel!
    
    @IBOutlet weak var humidityThresholdLabelOutlet: UILabel!
    
    @IBOutlet weak var humiditySetThresholdLabelOutlet: UILabel! {
        didSet {
            // TODO unhide threshold value area label if necessary
            humiditySetThresholdLabelOutlet.isHidden = true
        }
    }

    
    @IBOutlet weak var humidityAlertLabelOutlet: UILabel!
    
    @IBOutlet weak var manufacturerLabelOutlet: UILabel!
    
    @IBOutlet weak var modelNumberLabelOutlet: UILabel!
    
    @IBOutlet weak var serialNumberLabelOutlet: UILabel! {
        didSet {
            // TODO unhide serial number label if necessary
            serialNumberLabelOutlet.isHidden = true
        }
    }

    
    @IBOutlet weak var currentLabelOutlet: UILabel! {
        didSet {
            // TODO unhide current threshold label if necessary
            currentLabelOutlet.isHidden = true
        }
    }

    
    @IBOutlet weak var newLabelOutlet: UILabel!
    
    @IBOutlet weak var maximumLabelOutlet: UILabel! {
        didSet {
            // TODO unhide current threshold label if necessary
            maximumLabelOutlet.isHidden = true
        }
    }


    @IBOutlet weak var oldThresholdLabelOutlet: UILabel! {
        didSet {
            // TODO unhide old threshold label if necessary
            oldThresholdLabelOutlet.isHidden = true
        }
    }

    
    @IBOutlet weak var newThresoldTextFieldOutlet: UITextField!
    
    @IBOutlet var backToViewController4: UIButton! {
        didSet {
            backToViewController4.layer.cornerRadius = 6.0
            backToViewController4.layer.borderColor = UIColor.lightGray.cgColor
            backToViewController4.layer.borderWidth = 1.0
            backToViewController4.layer.backgroundColor = UIColor(white: 0.90,
                                                                  alpha: 1.0).cgColor
        }
    }
    
    @IBOutlet var exitApp: UIButton! {
        didSet {
            exitApp.layer.cornerRadius = 6.0
            exitApp.layer.borderColor = UIColor.lightGray.cgColor
            exitApp.layer.borderWidth = 1.0
            exitApp.layer.backgroundColor = UIColor(white: 0.90,
                                                    alpha: 1.0).cgColor
            // TODO unhide exit button            
            exitApp.isHidden = true
        }
    }

    @IBOutlet var applyButtonOutlet: UIButton! {
        didSet {
            applyButtonOutlet.layer.cornerRadius = 6.0
            applyButtonOutlet.layer.borderColor = UIColor.lightGray.cgColor
            applyButtonOutlet.layer.borderWidth = 1.0
            applyButtonOutlet.layer.backgroundColor = UIColor(white: 0.90,
                                                              alpha: 1.0).cgColor
        }
    }
    
    
    @IBOutlet var deviceIdLabelOutlet: UILabel!

    
    @IBAction func onBackButtonClick(_ sender: UIButton) {
        if !self.cvs[self.idx].hasSuffix(" %") {
            self.cvs[self.idx] = self.cvs[self.idx] + " %"
        }
        
        let userDefaults = UserDefaults.standard
        userDefaults.set(self.cvs, forKey: "currentValues")
        userDefaults.synchronize()
        
        DeviceSelectionView.first = false
        
        let fourthViewController = self.storyboard?.instantiateViewController(
            withIdentifier: "DeviceSelectionView") as! DeviceSelectionView
        self.navigationController?.pushViewController(fourthViewController,
                                                      animated: false)
    }
    
    
    @IBAction func onExitAppClick(_ sender: UIButton) {
        exit(0)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        UIGraphicsBeginImageContext(CGSize(width: self.view.frame.size.width,
                                           height: self.view.frame.size.width - 18))
        UIImage(named: "cloudes-sw.png")?.drawAsPattern(in: self.view.bounds)
        let image : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        SixthViewOutlet.backgroundColor = UIColor(patternImage: image)
        
        for dev in activeDevices {
            if dev.getEndpointId() == monitoredDevice {
                virtualDevice = dev
            }
        }
        
        // Monitor the selected device for humidity device model and update the 
        // UI view accordingly.
        if virtualDevice != nil {
            
            // Humidity values changes are managed.
            virtualDevice?.setOnChange(callback: { (event: ChangeEvent) in
                DispatchQueue.main.async(execute: {
                var namedValue = event.getNamedValue()
                var hasMore = true
                
                repeat  {
                    switch namedValue.getName() {
                    case "humidity":
                        humidity = namedValue.getValue()!.intValue
                        self.cvs[self.idx] = humidity.description
                        self.humidityValueLabelOutlet.text =
                            "\(kHumidity)\(self.cvs[self.idx]) %"
                        break
                    case "maxThreshold":
                        humidityThreshold = namedValue.getValue()!.intValue
                        self.humidityThresholdLabelOutlet.text =
                            "\(kHumidityThreshold)\(humidityThreshold.description) %"
                        self.oldThresholdLabelOutlet.text = humidityThreshold.description
                        break
                    default:
                        break
                    }
                    
                    if (namedValue.next() != nil) {
                        namedValue = namedValue.next()!
                    }
                    else {
                        hasMore = false
                    }
                }
                while (hasMore)
                })
            })
            
            // Humidity alerts are managed.
            virtualDevice?.setOnAlert(callback: { (event: AlertEvent) in
                DispatchQueue.main.async(execute: {
                let longUrn = event.getURN()
                let index = longUrn.range(of: ":", options: .backwards)?.lowerBound
                let shortUrn = longUrn[index!..<longUrn.endIndex]
                
                if (shortUrn == ":too_humid") {
                    self.humidityAlertLabelOutlet.text = kTooHumid
                    self.humidityAlertLabelOutlet.isHidden = false
                    // Loop for sample measurements
                    // Timers must be started on the main thread.
                    // This code is executed from the Alamofire response
                    // queue. This queue has been changed to be NOT the main
                    // queue.
                    // TODO: Shouldn't this value be saved in order to invalidate ?
                    DispatchQueue.main.async(execute: {
                        let _ = Timer.scheduledTimer(timeInterval: 3,
                            target: self, selector: #selector(self.hideAlert),
                            userInfo: nil, repeats: false)
                    })
                }
                })
            })
            
            // Humidity max threshold update errors are managed.
            virtualDevice?.setOnError(callback: { (event: ErrorEvent) in
                DispatchQueue.main.async(execute: {
                let errMessage = event.getMessage()
                print("Error message: " + errMessage)
                
                if errMessage == "User Authentication failed!" {
                    appDeviceModelsList.removeAll()
                    dmArray.removeAll()
                    urnArray.removeAll()
                    
                    activeDevices.removeAll()
                    deviceManufacturers.removeAll()
                    deviceModelNumbers.removeAll()
                    deviceSerialNumbers.removeAll()
                    
                    do {
                        try ecl.close()
                    } catch {
                        print("Error while closing enterprise client")
                    }
                    
                    let firstViewController = self.storyboard?.instantiateViewController(
                        withIdentifier: "ServerLoginView") as! ServerLoginView
                    self.navigationController?.pushViewController(firstViewController,
                                                                  animated: false)
                }
                
                let namedValue = event.getNamedValue()
                
                if namedValue.getName() == "maxThreshold" {
                    humidityThreshold = namedValue.getValue()!.intValue
                    self.humidityThresholdLabelOutlet.text = kHumidityThreshold +
                        humidityThreshold.description + " %"
                }
                })
            })
        }
    }
    
    override func viewWillAppear (_ animated: Bool) {
        self.navigationItem.setHidesBackButton(true, animated: false)
        deviceNameLabelOutlet.text = kHumiditySensor
        deviceIdLabelOutlet.text = monitoredDevice
        appNameLabelOutlet.font = .boldSystemFont(ofSize: 18.0)
        appNameLabelOutlet.text = kEnterpriseHeadLine
        manufacturerLabelOutlet.text = kManufacturer + monitoredDeviceManufacturer
        modelNumberLabelOutlet.text = kModelNumber + monitoredDeviceModelNumber
        serialNumberLabelOutlet.text = kSerialNumber + monitoredDeviceSerialNumber
        humiditySetThresholdLabelOutlet.text = kSetHumidityThreshold
        humidityAlertLabelOutlet.isHidden = true
        
        for dev in activeDevices {
            if dev.getEndpointId() == monitoredDevice {
                virtualDevice = dev
            }
        }
        
        let userDefaults = UserDefaults.standard
        self.cvs = userDefaults.array(forKey: "currentValues") as! [String]
        let ids = userDefaults.array(forKey: "idValues") as! [String]
        userDefaults.synchronize()
        
        let vdId = virtualDevice?.getEndpointId()
        for devId in ids {
            if devId == vdId {
                self.humidityValueLabelOutlet.text = kHumidity + self.cvs[self.idx]
                break
            }
            self.idx += 1
        }
        
        do {
            humidityThreshold =
                Int32(truncating: try virtualDevice?.get(attributeName: "maxThreshold") as! NSNumber)
            humidityThresholdLabelOutlet.text =
                "\(kHumidityThreshold)\(humidityThreshold.description) %"
        } catch { }
        
        currentLabelOutlet.text = kCurrent
        newLabelOutlet.text = kNew
        maximumLabelOutlet.text = kMaximum
        oldThresholdLabelOutlet.text = humidityThreshold.description
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @objc func hideAlert() {
         self.humidityAlertLabelOutlet.isHidden = true
    }
    
    // actions
    
    // Action to apply changes on humidity threshold.
    @IBAction func onApplyClick(_ sender: UIButton) {

        let newThresholdString = newThresoldTextFieldOutlet.text!
        let testInt = Int(newThresholdString)
        if(testInt == nil) {
            showError(controller: self, alertTitle: "Threshold Setting Alert",
                      message: kThresholdSettingAlert, actionTitle: "OK",
                      handler: { (action:UIAlertAction?) -> () in
                self.newThresoldTextFieldOutlet.text = ""
            })
        } else {
            let oldHumidityThreshold = humidityThreshold
            humidityThreshold = Int32(testInt!)
            newThresoldTextFieldOutlet.text = ""
            oldThresholdLabelOutlet.text = humidityThreshold.description
            self.humidityThresholdLabelOutlet.text =
                "\(kHumidityThreshold)\(humidityThreshold.description) %"

            do {
                let newValue = NSNumber(value: humidityThreshold as Int32)
                let _ = try self.virtualDevice?.set(attributeName: "maxThreshold",
                                        attributeValue: newValue as AnyObject)
            } catch ClientError.argument(let error) {
                print(error)
                showError(controller: self, alertTitle: "Threshold Setting Alert",
                          message: error, actionTitle: "OK",
                          handler: { (action:UIAlertAction?) -> () in
                    humidityThreshold = oldHumidityThreshold
                    self.humidityThresholdLabelOutlet.text =
                        "\(kHumidityThreshold)\(humidityThreshold.description) %"
                })
            } catch  {
                print(error)
                showError(controller: self, alertTitle: "Humidity Alert",
                          message: "\(error)", actionTitle: "OK",
                          handler: { (action:UIAlertAction?) -> () in
                    humidityThreshold = oldHumidityThreshold
                    self.humidityThresholdLabelOutlet.text =
                        "\(kHumidityThreshold)\(humidityThreshold.description) %"
                })
            }
        }
    }
}
