/*
	Copyright (C) 2016 Apple Inc. All Rights Reserved.
	See LICENSE.txt for this sample’s licensing information
	
	Abstract:
	This file contains the StatusViewController class, which controls a view used to start and stop a VPN connection, and display the status of the VPN connection.
    该文件包含StatusViewController类，该类控制用于启动和停止VPN连接的视图，并显示VPN连接的状态。
*/

import UIKit
import NetworkExtension
import SimpleTunnelServices

// MARK: Extensions

/// Make NEVPNStatus convertible to a string
extension NEVPNStatus: CustomStringConvertible {
    public var description: String {
        switch self {
        	case .disconnected: return "Disconnected"
        	case .invalid: return "Invalid"
        	case .connected: return "Connected"
        	case .connecting: return "Connecting"
        	case .disconnecting: return "Disconnecting"
        	case .reasserting: return "Reconnecting"
        }
    }
}

/// A view controller object for a view that displays VPN status information and allows the user to start and stop the VPN.
class StatusViewController: UITableViewController {

	// MARK: Properties

	/// A switch that toggles the enabled state of the VPN configuration.
	@IBOutlet weak var enabledSwitch: UISwitch!

	/// A switch that starts and stops the VPN.
	@IBOutlet weak var startStopToggle: UISwitch!

	/// A label that contains the current status of the VPN.
	@IBOutlet weak var statusLabel: UILabel!

	/// The target VPN configuration.
	var targetManager = NEVPNManager.shared()

	// MARK: UIViewController

	/// Handle the event where the view is being displayed.
	override func viewWillAppear(_ animated: Bool) {
		super.viewWillAppear(animated)

		// Initialize the UI
		enabledSwitch.isOn = targetManager.isEnabled
		startStopToggle.isOn = (targetManager.connection.status != .disconnected && targetManager.connection.status != .invalid)
		statusLabel.text = targetManager.connection.status.description
		navigationItem.title = targetManager.localizedDescription

		// Register to be notified of changes in the status.
		NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: targetManager.connection, queue: OperationQueue.main, using: { notification in
            if self.targetManager.connection.status == .disconnected || self.targetManager.connection.status == .disconnecting {
                
            }
			self.statusLabel.text = self.targetManager.connection.status.description
			self.startStopToggle.isOn = (self.targetManager.connection.status != .disconnected && self.targetManager.connection.status != .disconnecting && self.targetManager.connection.status != .invalid)
		})

		// Disable the start/stop toggle if the configuration is not enabled.
		startStopToggle.isEnabled = enabledSwitch.isOn

		// Send a simple IPC message to the provider, handle the response.
		if let session = targetManager.connection as? NETunnelProviderSession,
			let message = "Hello Provider".data(using: String.Encoding.utf8)
			, targetManager.connection.status != .invalid
		{
			do {
				try session.sendProviderMessage(message) { response in
					if response != nil {
						let responseString = NSString(data: response!, encoding: String.Encoding.utf8.rawValue)
						simpleTunnelLog("Received response from the provider: \(responseString)")
					} else {
						simpleTunnelLog("Got a nil response from the provider")
					}
				}
			} catch {
				simpleTunnelLog("Failed to send a message to the provider")
			}
		}
	}

	/// Handle the event where the view is being hidden.
	override func viewWillDisappear(_ animated: Bool) {
		super.viewWillDisappear(animated)

		// Stop watching for status change notifications.
		NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: targetManager.connection)
	}

	/// Handle the user toggling the "enabled" switch.
	@IBAction func enabledToggled(_ sender: AnyObject) {
		targetManager.isEnabled = enabledSwitch.isOn
		targetManager.saveToPreferences { error in
			guard error == nil else {
				self.enabledSwitch.isOn = self.targetManager.isEnabled
				self.startStopToggle.isEnabled = self.enabledSwitch.isOn
				return
			}
			
			self.targetManager.loadFromPreferences { error in
				self.enabledSwitch.isOn = self.targetManager.isEnabled
				self.startStopToggle.isEnabled = self.enabledSwitch.isOn
			}
		}
	}

	/// Handle the user toggling the "VPN" switch.
	@IBAction func startStopToggled(_ sender: AnyObject) {
		if targetManager.connection.status == .disconnected || targetManager.connection.status == .invalid {
			do {
				try targetManager.connection.startVPNTunnel()
			}
			catch {
				simpleTunnelLog("Failed to start the VPN: \(error)")
			}
		}
		else {
			targetManager.connection.stopVPNTunnel()
		}
	}
}
