/*
 *  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 DeviceModelSelectionView: UIViewController, UITableViewDelegate,
                                                  UITableViewDataSource {

    @objc var listLength:Int = 0
    
    @IBOutlet var ThirdViewOutlet: UIView!
    
    @IBOutlet weak var headLineLabelOutlet: UILabel!
    
    @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
        }
    }

    
    @IBAction func onExitAppClick(_ sender: UIButton) {
        exit(0)
    }
    
    @IBOutlet var backToViewController2: UIButton! {
        didSet {
            backToViewController2.layer.cornerRadius = 6.0
            backToViewController2.layer.borderColor = UIColor.lightGray.cgColor
            backToViewController2.layer.borderWidth = 1.0
            backToViewController2.layer.backgroundColor = UIColor(white: 0.90,
                                                                  alpha: 1.0).cgColor
            // TODO unhide back button if necessary
            backToViewController2.isHidden = true
        }
    }

    
    @IBOutlet weak var deviceModelsLabelOutlet: UILabel!
    
    @IBOutlet weak var tableView: UITableView!
    
    @IBAction func onBackButtonClick(_ sender: UIButton) {
        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 secondViewController = self.storyboard?.instantiateViewController(
            withIdentifier: "ApplicationSelectionView") as! ApplicationSelectionView
        self.navigationController?.pushViewController(secondViewController,
                                                      animated: false)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.tableView.delegate = self
        self.tableView.dataSource = self
        
        self.tableView.register(UITableViewCell.self,
                                forCellReuseIdentifier: "cell")
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.deviceTypes.count
    }

    @objc var deviceTypes: [String] = []
    
    // Fill the table view with device models.
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")!
        cell.textLabel?.textAlignment = NSTextAlignment.left
        cell.textLabel!.text = self.deviceTypes[indexPath.row]
        
        cell.accessoryType = .disclosureIndicator
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.tableView.cellForRow(at: indexPath)?.selectionStyle = .gray
        self.getDevices(index: indexPath.row)
    }

    override func viewWillAppear (_ animated: Bool) {
        self.navigationItem.setHidesBackButton(true, animated: false)
        
        headLineLabelOutlet.font = .boldSystemFont(ofSize: 18.0)
        headLineLabelOutlet.text = kEnterpriseHeadLine

        deviceModelsLabelOutlet.textAlignment = .center
        deviceModelsLabelOutlet.text = kDeviceModels
        
        listLength = dmArray.count
        for index in 0...(listLength - 1) {
            self.deviceTypes.append(dmArray[index])
        }
    }
    
    override func viewDidAppear (_ animated: Bool) {
        super.viewDidAppear(animated)
        
        self.tableView.flashScrollIndicators()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // actions
    
    // Action for one row selection. Active devices are got according to the 
    // selected device model.
    @objc func getDevices(index: Int) {
        let dm = appDeviceModelsList[index]
        
        var deviceNumber = 0
        var errorMessage = String()
        
        activeDevices = []
        
        // return true if the error is a UserAuth error
        func handleUserAuthError(ecl: EnterpriseClient?, error: ClientError) -> Bool {
            let autherr = NSLocalizedString(
                "User Authentication failed. Session cookie has expired.",
                comment: "")
            if "\(error)".range(of: autherr) != nil {
                if let ecl = ecl {
                    do {
                        try ecl.close()
                    } catch {
                        print("\(error)")
                    }
                }
                
                showError(controller: self, alertTitle: "User Auth Alert",
                          message: autherr, actionTitle: "Login",
                          handler: { (action:UIAlertAction?) -> () in
                    let firstViewController = self.storyboard?.instantiateViewController(
                        withIdentifier: "ServerLoginView") as! ServerLoginView
                    self.navigationController?.pushViewController(firstViewController,
                                                                  animated: false)
                })
                return true
            } else {
                print("\(error)")
                showError(controller: self, alertTitle: "Device Alert",
                    message: "\(error)", actionTitle: "OK",
                    handler: {(action:UIAlertAction?) -> () in
                    return
                })
                return false
            }
        }
        
        // Get active device list for the selected URN.
        ecl.getActiveDevices(deviceModel: dm.getURN(), callback: { (pageable, error) in
            if let error = error {
                // An error has encountered during getting the active devices.
                if (handleUserAuthError(ecl: ecl, error: error)) {
                    appDeviceModelsList.removeAll()
                    dmArray.removeAll()
                    urnArray.removeAll()
                 }
                return
            }
            
            // Process the active devices recursively.
            func recursivePaging (pageable: Pageable<Device>?, error: ClientError?) {
                do {
                    if let error = error {
                        // An error has encountered during the active devices paging.
                        if handleUserAuthError(ecl: ecl, error: error) {
                            appDeviceModelsList.removeAll()
                            dmArray.removeAll()
                            urnArray.removeAll()
                            
                            activeDevices.removeAll()
                            deviceManufacturers.removeAll()
                            deviceModelNumbers.removeAll()
                            deviceSerialNumbers.removeAll()
                        }
                        return
                    }
                        
                    // If there are no devices to process return
                    if (pageable!.size() == 0) {
                        return
                    }
                    
                    // Create virtual devices and save them into a list.
                    for device: Device in pageable!.elements() {
                        let dId = device.getId()
                        let vd: VirtualDevice = ecl.createVirtualDevice(deviceId: dId, deviceModel: dm)
                        activeDevices.append(vd)
                        
                        deviceManufacturers.append(device.getValue(field: Device.Field.fromAlias(alias: "manufacturer")))
                        deviceModelNumbers.append(device.getValue(field: Device.Field.fromAlias(alias: "modelNumber")))
                        deviceSerialNumbers.append(device.getValue(field: Device.Field.fromAlias(alias: "serialNumber")))
                        
                        let dmURN = dm.getURN()
                        let metadata = device.getMetadata()
                        if dmURN == IBEACON_DEVICE_MODEL_URN {
                            deviceUUID.append(metadata["UUID"] ?? "Unknown")
                            deviceMinor.append(metadata["minor"] ?? "Unknown")
                            deviceMajor.append(metadata["major"] ?? "Unknown")
                        }
                        if dmURN == EDDYSTONEBEACONTLMUID_DEVICE_MODEL_URN {
                            deviceUUID.append(metadata["UUID"] ?? "Unknown")
                        }
                        
                        deviceNumber += 1
                        if deviceNumber == pageable!.size() {
                            let userDefaults = UserDefaults.standard
                            userDefaults.set([], forKey: "currentValues")
                            userDefaults.set([], forKey: "idValues")
                            userDefaults.synchronize()
                            
                            DispatchQueue.main.async(execute: {
                            let fourthViewController = self.storyboard?.instantiateViewController(withIdentifier: "DeviceSelectionView") as! DeviceSelectionView
                            self.navigationController?.pushViewController(fourthViewController, animated: true)
                            })
                            return
                        }
                        
                    }
                    
                    if (pageable!.hasMore()) {
                        try pageable!.next(callback: recursivePaging)
                    } else {
                        return
                    }
                } catch {
                    print(error)
                    showError(controller: self, alertTitle: "Device Alert",
                        message: "\(error)", actionTitle: "OK", handler: nil)
                }
            }
            
            recursivePaging(pageable: pageable, error: error)
        })
    }
}

