//
//  OptionsViewController.swift
//  ABC Bluetooth Demo
//
//  Created by AB Circle on 23/11/2020.
//  Copyright © 2020-2024 AB Circle. All rights reserved.
//

import UIKit

/// Delegate protocol for delegate classes to implement
protocol OptionsViewControllerProtocol : NSObjectProtocol {
    
    /// Call back function definition to implement for handling the closing of the Custom Key view
    /// and retrieving the inputted values.
    ///
    /// - Parameters:
    ///   - options: class holding all options
    func onCloseOptionsWindow(options: Options)
}

/// Controller for handling the Custom Key input, readername filter and RSSI filter
class OptionsViewController: UIViewController {
    
    /// :nodoc: View controller identifier
    static let identifier   = "OptionsViewController"
    
    /// delegate, set this to the class acting as delegate for this class using the CustomKeyViewControllerProtocol
    private weak var delegate: OptionsViewControllerProtocol?
    
    /// Options storage
    private let options = Options()
    
    /// :nodoc: Step value for battery threshold
    let stepValue: Float = 20
    
    /// Control outlet for Key Type UISegmentedControl
    @IBOutlet weak var segmentedKeyType: UISegmentedControl!
    /// Control outlet for Custom Key HexEditUITextView
    @IBOutlet weak var customKeyTextView: HexEditUITextView!
    /// Control outlet for Name Filter UITextField
    @IBOutlet weak var nameFilterTextField: UITextField!
    /// Control outlet for RSSI Filter UITextField
    @IBOutlet weak var rssiFilterTextField: NumericUITextField!
    /// Control outlet for refresh rate slider
    @IBOutlet weak var sliderRefresh: UISlider!
    /// Control outlet for refresh rate UILabel
    @IBOutlet weak var labelRefresh: UILabel!
    /// Control outlet for battery threshold UISlider
    @IBOutlet weak var sliderThreshold: UISlider!
    /// Control outlet for battery threshold UILabel
    @IBOutlet weak var labelThreshold: UILabel!
    /// Control outlet for ACK Protocol UISwitch
    @IBOutlet weak var switchACKProtocol: UISwitch!
    /// Control outlet for ACK Protocol Text UILabel
    @IBOutlet weak var labelACKProtocolText: UILabel!
    
    /// Called after the controller's view is loaded into memory.
    /// Initialises the local variables, the controls and starts the terminal list updater
    override func viewDidLoad() {
        super.viewDidLoad()
        
        initialiseTextView(textView: customKeyTextView)
        
        segmentedKeyType.selectedSegmentIndex = (options.useDefaultKey ? 0 : 1)
        customKeyTextView.text      = options.customKeyString
        nameFilterTextField.text    = options.nameFilter
        rssiFilterTextField.text    = String(options.rssiFilter, radix: 10)
        sliderRefresh.value         = Float(options.monitorRefreshRate)
        sliderThreshold.value       = Float(options.monitorBatteryThreshold)
        switchACKProtocol.isOn      = options.ackEnabled
        
        setLabelRefreshRate(value: options.monitorRefreshRate)
        setLabelThreshold(value: options.monitorBatteryThreshold)
        setLabelACKProtocol(value: options.ackEnabled)
        
        enableUIFields()
    }
    
    /// Sets the initial values of the view
    ///
    /// - Parameters:
    ///   - parentViewController: Parent controller to use as delegate
    ///   - useDefaultKey: Initial flag indicating if default key is used
    ///   - customKey: Initial custom key
    func setInitialValues(parentViewController: UIViewController, options: Options) {
        self.delegate = parentViewController as? OptionsViewControllerProtocol
        self.options.set(newOptions: options)
    }
    
    /// Handles key type change
    ///
    /// - Parameter sender: UI control
    @IBAction func onKeyTypeChanged(_ sender: UISegmentedControl) {
        options.useDefaultKey = (sender.selectedSegmentIndex == 0)
        enableUIFields()
    }
    
    /// Handles setting and showing of refresh rate
    ///
    /// - Parameter sender: UISlider control
    @IBAction func onRefreshValueChanged(_ sender: UISlider) {
        let refreshRate = UInt16(sliderRefresh.value)

        options.monitorRefreshRate = refreshRate
        setLabelRefreshRate(value: options.monitorRefreshRate)
    }
    
    /// Handles setting and showing of battery threshold
    ///
    /// - Parameter sender: UISlider control
    @IBAction func onThresholdValueChanged(_ sender: UISlider) {
        let threshold  = round(sliderThreshold.value / stepValue) * stepValue
        
        sliderThreshold.value           = threshold
        options.monitorBatteryThreshold = UInt8(threshold)
        setLabelThreshold(value: options.monitorBatteryThreshold)
    }
    
    /// Handles enabling or disabling ACK protocol (for readers with fw 109.00 or higher)
    ///
    /// - Parameter sender: UISwitch control
    @IBAction func onACKProtocolChanged(_ sender: UISwitch) {
        options.ackEnabled = sender.isOn
        setLabelACKProtocol(value: options.ackEnabled)
    }
    
    /// OK button handler
    ///
    /// - Parameter sender: UI control
    @IBAction func onOKClicked(_ sender: UIButton) {
        if let rssi = rssiFilterTextField.text {
            options.rssiFilter = (Int(rssi) ?? 0)
        }
        else {
            options.rssiFilter = 0
        }
        options.customKeyString = customKeyTextView.text
        options.nameFilter      = nameFilterTextField.text ?? ""
        if options.useDefaultKey {
            
            delegate?.onCloseOptionsWindow(options: options)
            closeThis()
        }
        else {
            if Helper.hexStringToData(hexString: customKeyTextView.text).count == 16 {
                delegate?.onCloseOptionsWindow(options: options)
                closeThis()
            }
            else {
                let alert = UIAlertController(title: "Warning", message: "Custom key must be 16 bytes long", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: "Default action"), style: .default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }
        }
    }
    
    /// Close button handler
    ///
    /// - Parameter sender: UI control
    @IBAction func onCloseClicked(_ sender: UIButton) {
        closeThis()
    }
    
    /// Initialises the text view properties
    ///
    /// - Parameter textView: Textview control to initialise
    private func initialiseTextView(textView: UITextView)
    {
        textView.autocapitalizationType = .allCharacters
        textView.text                   = ""
        textView.layer.borderWidth      = 1.0
        textView.layer.cornerRadius     = 8
        textView.layer.borderColor      =  UIColor.lightGray.cgColor
    }
    
    /// Enable or disable UI
    private func enableUIFields() {
        if options.useDefaultKey {
            customKeyTextView.isEditable    = false
        }
        else {
            customKeyTextView.isEditable    = true
        }
    }
    
    /// Sets value label for monitor refresh rate
    ///
    /// - Parameter value: Refresh rate value
    private func setLabelRefreshRate(value: UInt16) {
        switch value {
            case 0:
                labelRefresh.text = "Off"
            case 1:
                labelRefresh.text = "\(value) second"
            default:
                labelRefresh.text = "\(value) seconds"
        }
    }
    
    /// Sets ACK Protocol text label
    ///
    /// - Parameter value: ACK protocol value
    private func setLabelACKProtocol(value: Bool) {
        if value {
            labelACKProtocolText.text = "Enabled (fw 109.00 or higher only)"
        }
        else {
            labelACKProtocolText.text = "Disabled"
        }
    }
    
    /// Sets value label for monitor battery threshold
    ///
    /// - Parameter value: Battery threshold value
    private func setLabelThreshold(value: UInt8) {
        if value == 0 {
            labelThreshold.text = "Not monitored"
        }
        else {
            labelThreshold.text = "\(value) %"
        }
    }
    
    /// Closes this view
    private func closeThis() {
        self.dismiss(animated: true, completion: nil)
    }
}
