/*
 *  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

// The filename for the Network Provisioned file
fileprivate let kNetProvFile = "bootstrapper.conf"
fileprivate var bootstrapper:Bootstrapper?
fileprivate var bootstrapping:Bool = false

fileprivate func bootstrapperStop() {
    bootstrapper?.stop()
    bootstrapping = false
    bootstrapper = nil
}

class NetworkProvisioningPasswordView: PasswordView {

    // Requires the application to create Main.storyboard
    // and an intial view controller
    private var MainStoryboard: UIStoryboard? = nil
    

    @IBOutlet weak var activityOutlet: UIActivityIndicatorView! {
        didSet {
            activityOutlet.activityIndicatorViewStyle = .whiteLarge
            let transform: CGAffineTransform =
                CGAffineTransform(scaleX: 4.0, y: 4.0)
            activityOutlet.transform = transform
            activityOutlet.color = UIColor.black
            activityOutlet.hidesWhenStopped = true
        }
    }

    override func viewDidLoad() {
        if MainStoryboard == nil {
            MainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        }
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        if MainStoryboard == nil {
            MainStoryboard = UIStoryboard(name: "Main", bundle: nil)
        }
        passwordOutlet.isEnabled = true
        super.viewWillAppear(animated)
    }
    
    // Only two ways to leave the password screen
    // Clicking keyboard Continue or nav bar Cancel
    override func viewWillDisappear(_ animated:Bool) {
        if bootstrapping {
            bootstrapper?.cancel()
            // May not have to care since this root controller will be the
            //  previous controller, for now
            //self.navigationController?.popToRootViewController(animated: false)
        }
        bootstrapperStop()
        super.viewWillDisappear(animated)
    }

    override func verifyPassword(password: String) -> Bool {
        return true
    }

    override func handleOk(button: UIButton) {
        networkProvision()
    }
    
    @objc func successView() {
        bootstrapperStop()
        
        saveSettingsFile(path: kNetProvFile, password: getPassword())
        let path = FileParser.sharedInstance.documentsURL().appendingPathComponent(
            kNetProvFile, isDirectory: false)
        Provisioning.setProvisioningFilePath(pf: path.path)
        Provisioning.setProvisioningPassword(pp: getPassword())
        
        // Every App that wants to use generic File and Network bootstrapping
        // must have an "Main" storyboard with at one view controller
        // tagged as the "initial view controller"
        if self.activityOutlet.isAnimating {
            self.activityOutlet.stopAnimating()
        }
        // HACK: To see if navigation controls are propogated correctly
        // when the view is in another storyboard. Need this to perform
        // ssegue
        okButtonOutlet.sendActions(for: .touchUpInside)
        /*
        self.navigationController?.pushViewController(
            (self.MainStoryboard?.instantiateInitialViewController())!,
            animated: true)
        */
    }
    
    @objc func failView(_ action:UIAlertAction) {
        if self.activityOutlet.isAnimating {
            self.activityOutlet.stopAnimating()
        }
        let _ = self.navigationController?.popToRootViewController(animated: false)
        bootstrapperStop()
    }
    
    @objc func networkProvision() {
        self.activityOutlet.startAnimating()
        DispatchQueue.global().async(execute: {
            self.networkProvisioning(filename: getDocumentPath(file: kNetProvFile),
                                password: self.getPassword(),
                                failView: self.failView,
                                successView: self.successView)
        })
    }

    @objc func networkProvisioning(filename: String, password: String,
                             failView: @escaping ((UIAlertAction) -> ()),
                             successView: @escaping (() -> ()))  {
        
        bootstrapping = true
        bootstrapper = Bootstrapper(taStore: filename,
                                    taStorePassword: password,
                                    provisionFileCallback: { (status) in
            switch status {
            // Bad format or an exception occurred
            case 0x01:
                showError(controller: self, alertTitle: "Provisioning Alert",
                          message: "Provisioning was unsuccessful, format was not correct.",
                          actionTitle: "OK",
                          handler: failView)
                break
            // File downloaded and validated
            case 0x02:
                if !FileManager.default.fileExists(atPath: filename) {
                    // Shouldn't happen since this was checked in the bootstrapper
                    //bootstrapper?.notProvisioned()
                    showError(controller: self, alertTitle: "Provisioning Alert",
                              message: "The \(filename) file does not exist.",
                        actionTitle: "OK",
                        handler: failView)
                    return
                }
                
                // TODO: pop this view off the navigator stack so that the
                // password screen if cancelled will got directly to the
                // chooser view
                DispatchQueue.main.async(execute:
                    /*
                    let detail = self.storyboard?.instantiateViewController(
                        withIdentifier: "NetworkProvisioningPasswordView") as! NetworkProvisioningPasswordView
                    self.navigationController?.pushViewController(detail,
                                                                  animated: false)
                    */
                    successView
                )
                break
            // File does not exist
            case 0x03:
                showError(controller: self,alertTitle: "Provisioning Alert",
                          message: "Provisioning was unsuccessful.",
                          actionTitle: "OK",
                          handler: failView)
                break
            // Don't see this state in the Bootstrapper.
            case 0x04:
                showError(controller: self,alertTitle: "Provisioning Alert",
                          message: "Error during getting data from truststore.",
                          actionTitle: "OK",
                          handler: failView)
                break
                
            default:
                break
            }
        })
    }

}

class NetworkProvisioningView: UIViewController {

    private var passwordDidDisplay:Bool = false
    
    @IBOutlet weak var activityOutlet: UIActivityIndicatorView! {
        didSet {
            activityOutlet.activityIndicatorViewStyle = .whiteLarge
            let transform: CGAffineTransform = CGAffineTransform(scaleX: 4.0,
                                                                 y: 4.0)
            activityOutlet.transform = transform
            activityOutlet.color = UIColor.black
            activityOutlet.hidesWhenStopped = true
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        if !passwordDidDisplay {
            self.activityOutlet.startAnimating()
            //DispatchQueue.global().async(execute: networkProvisioning)
            super.viewWillAppear(animated)
        }
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        // The activity screen is cancelled
        if self.activityOutlet.isAnimating {
            self.activityOutlet.stopAnimating()
        }
        if !passwordDidDisplay {
            //bootstrapper?.notProvisioned()
            bootstrapperStop()
        }
        super.viewWillDisappear(animated)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}
