/*
 *  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 ApplicationSelectionView: UIViewController {

    @IBOutlet var SecondViewOutlet: UIView!
    
    @IBOutlet weak var headLineLabelOutlet: UILabel!
    
    @IBOutlet weak var iotApplicationLabelOutlet: UILabel!
    
    @IBOutlet weak var oracleLogoImageViewOutlet: UIImageView! {
        didSet {
            oracleLogoImageViewOutlet.image = UIImage(named: "oracle_iot.png")
        }
    }
    
    @IBOutlet weak var attentionImageViewOutlet: UIImageView! {
        didSet {
            attentionImageViewOutlet.image = UIImage(named: "attention.png")
        }
    }
    

    @IBOutlet weak var applicationNameTextfieldOutlet: UITextField! {
        didSet {
            applicationNameTextfieldOutlet.layer.cornerRadius = 6.0
            applicationNameTextfieldOutlet.layer.borderColor = UIColor.lightGray.cgColor
            applicationNameTextfieldOutlet.layer.borderWidth = 1.0
            applicationNameTextfieldOutlet.layer.backgroundColor = UIColor(white: 0.90,
                                                                           alpha: 1.0).cgColor
        }
    }

    @IBOutlet weak var nextButtonOutlet: UIButton! {
        didSet {
            nextButtonOutlet.layer.cornerRadius = 6.0
            nextButtonOutlet.layer.borderColor = UIColor.lightGray.cgColor
            nextButtonOutlet.layer.borderWidth = 1.0
            nextButtonOutlet.layer.backgroundColor = UIColor(white: 0.90,
                                                             alpha: 1.0).cgColor
        }
    }
    
    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()
        SecondViewOutlet.backgroundColor = UIColor(patternImage: image)
        attentionImageViewOutlet.isHidden = true
    }

    override func viewWillAppear (_ animated: Bool) {
        self.navigationItem.setHidesBackButton(true, animated: false)
        
        if applicationName.isEmpty == false {
            applicationNameTextfieldOutlet.text = applicationName
        }
        
        headLineLabelOutlet.font = .boldSystemFont(ofSize: 18.0)
        headLineLabelOutlet.text = kEnterpriseHeadLine
        iotApplicationLabelOutlet.font = .boldSystemFont(ofSize: 15.0)
        iotApplicationLabelOutlet.text = kIotApplication
        nextButtonOutlet.setTitle(kNext, for: UIControlState())
        applicationNameTextfieldOutlet.placeholder = kAppNameTextFieldHint
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    
    // actions
    
    @objc var processed: Bool = false
    
    // Action for next button. The enteprise client is created, device model 
    // list and details are obtained for user authentication scheme.
    @IBAction func onNextButton(_ sender: UIButton) {
        
        // Return true if error is an UserAuthError, else false
        func handleUserAuthError(eclClient: EnterpriseClient?, error: ClientError) -> Bool {
            let autherr = NSLocalizedString(
                "User Authentication failed. Session cookie has expired.",
                comment: "")
            if "\(error)".range(of: autherr) != nil {
                if let eclClient = eclClient {
                    do {
                        try eclClient.close()
                    } catch {
                        print("\(error)")
                    }
                }
                showError(controller: self, alertTitle: "User Auth Alert",
                          message: autherr, actionTitle: "Login",
                          handler: { (action:UIAlertAction?) -> Void 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: "App Alert",
                          message: "\(error)", actionTitle: "OK",
                          handler: {(action:UIAlertAction?) -> Void in
                            return
                })
                return false
            }
        }
        applicationName = applicationNameTextfieldOutlet.text!
        
        // Create the enterprise client. Application name is selected in the 
        // provided list.
        EnterpriseClient.newClient(appName: applicationName, path: Provisioning.getProvisioningFilePath(),
            password: Provisioning.getProvisioningPassword(),  callback: { eclClient, error in
            if ((error != nil) || (eclClient == nil)) {
                // An error has encountered during enterprise client creation.
                let _ = handleUserAuthError(eclClient: nil, error: error!)
                return
            } else {
                if eclClient!.getApplication().getName().isEmpty == false {
                    ecl = eclClient
                    
                    var dmNumber = 0
                    // Get device model list associated to the selected application.
                    eclClient!.getDeviceModels(callback: { (pageable, error) in
                        if let error = error {
                            // An error has encountered during getting the device model list.
                            let _ = handleUserAuthError(eclClient: eclClient,
                                                        error: error)
                            return
                        }
                        
                        // Process the device model recursively.
                        //var recursivePaging: (Pageable<String>?,ClientError?) -> Void = { $0 }
                        func recursivePaging (pageable: Pageable<String>?, error: ClientError?) {
                            do {
                                if let error = error {
                                    // An error has encountered during the device model paging.
                                    if handleUserAuthError(eclClient: eclClient,
                                                           error: error) {
                                        appDeviceModelsList.removeAll()
                                        dmArray.removeAll()
                                        urnArray.removeAll()
                                    }
                                    return
                                }
                                // If there are no device models to process return
                                if (pageable!.size() == 0) {
                                    return
                                }
                                                                    
                                for urn: String in pageable!.elements() {
                                    // Get details for one single device model.
                                    try eclClient!.getDeviceModel(deviceModelUrn: urn,
                                        callback: { deviceModel, error in
                                        if (error == nil) {
                                            if let dmObject = deviceModel {
                                                appDeviceModelsList.append(dmObject)
                                                dmArray.append(dmObject.getName())
                                                urnArray.append(dmObject.getURN())
                                                
                                                dmNumber += 1
                                                if dmNumber == pageable!.size() {
                                                    DispatchQueue.main.async(execute: {
                                                    let thirdViewController = self.storyboard?.instantiateViewController(withIdentifier: "DeviceModelSelectionView") as! DeviceModelSelectionView
                                                    self.navigationController?.pushViewController(thirdViewController, animated: true)
                                                    })
                                                }
                                            }
                                        } else {
                                            // An error has encountered during getting the device model details.
                                            if handleUserAuthError(eclClient: eclClient, error: error!) {
                                                appDeviceModelsList.removeAll()
                                                dmArray.removeAll()
                                                urnArray.removeAll()
                                            }
                                            return
                                        }
                                    })
                                }
                                
                                if (pageable!.hasMore()) {
                                    try pageable!.next(callback: recursivePaging)
                                } else {
                                    return
                                }
                            } catch {
                                print(error)
                                showError(controller: self,
                                          alertTitle: "Device Model Alert",
                                          message: "\(error)",
                                          actionTitle: "OK", handler: nil)
                            }
                        }
                        
                        recursivePaging(pageable: pageable, error: error)
                    })
                } else {
                    print(error!)
                    showError(controller: self,
                        alertTitle: "Enterprise Client Alert",
                        message: "Enterprise Client object has not been created.",
                        actionTitle: "OK", handler: nil)
                }
            }
        })
    }
    
    @IBAction func onAppNameChanged(_ sender: UITextField) {
        self.nextButtonOutlet.isEnabled = true
    }
}
