//
//  MainViewController.swift
//  GetGeoDemo
//
//  Created by CT-Armin.Budiman on 3/9/20.
//  Copyright © 2020 Cartrack. All rights reserved.
//

import UIKit
import CoreBluetooth
import CartrackBleLockSDK

class MainViewController: UIViewController {

    var bleTerminal: BleTerminal?
    
    @IBOutlet weak var connectButton: UIButton!
    @IBOutlet weak var disconnectButton: UIButton!
    @IBOutlet weak var unlockButton: UIButton!
    @IBOutlet weak var lockButton: UIButton!
    @IBOutlet weak var headlightButton: UIButton!
    @IBOutlet weak var hornButton: UIButton!
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var rssiLabel: UILabel!
    @IBOutlet weak var lockStateLabel: UILabel!
    @IBOutlet weak var lockStateButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        BleService.configure(vendorID: "227020", apiKey: "97084cbb-deaf-471c-8e9d-b920f0f8b798")
        rssiLabel.text = ""
        updateViewsState()
        
        nameTextField.text = UserDefaults.standard.value(forKey: "terminal_id") as? String ?? ""
    }
    
    @IBAction func connectButtonTapped(_ sender: Any) {
        if nameTextField.text?.isEmpty ?? true {
            showMessage(title: "", message: "Please enter a Terminal ID")
            return
        }
        
        nameTextField.resignFirstResponder()
        bleTerminal = BleService.getTerminal(terminalID: nameTextField.text!)
        bleTerminal?.delegate = self
        
        if bleTerminal?.hasKey ?? false {
            LoaderView.show("Connecting")
            bleTerminal?.connect()
        } else {
            LoaderView.show("Fetching Key")
            bleTerminal?.getAuthKey()
        }
        updateViewsState()
        
        UserDefaults.standard.set(nameTextField.text, forKey: "terminal_id")
    }
   
    @IBAction func disconnectButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.disconnect()
    }
    
    @IBAction func unlockButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.sendAction(.unlock)
        updateViewsState()
    }
    
    @IBAction func lockButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.sendAction(.lock)
        updateViewsState()
    }
    
    @IBAction func headlightButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.sendAction(.headlight)
        updateViewsState()
    }
    
    @IBAction func hornButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.sendAction(.horn)
        updateViewsState()
    }
    
    @IBAction func lockStateButtonTapped(_ sender: Any) {
        LoaderView.show()
        bleTerminal?.sendAction(.lockState)
        updateViewsState()
    }
    
    private func showMessage(title: String, message: String) {
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
        self.present(alertController, animated: true, completion: nil)
    }
    
    private func updateViewsState() {
        let initialized = bleTerminal != nil
        let connectionState = bleTerminal?.connectionState ?? BleConnectionState.disconnected
        
        connectButton.isEnabled = connectionState == .disconnected
        disconnectButton.isEnabled = connectionState == .connected
        lockStateLabel.text = "Lock State: \(bleTerminal?.lockState ?? .unknown)".capitalized
        
        [unlockButton, lockButton, headlightButton, hornButton, lockStateButton].forEach {
            $0?.isEnabled = initialized && connectionState == .connected
        }
        
    }

}

extension MainViewController: UITextFieldDelegate {
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        connectButtonTapped(textField)
        return true
    }
    
}

extension MainViewController: BleTerminalDelegate {
    
    func bleTerminalDidGetKey(terminal: BleTerminal, error: BleKeyError?) {
        updateViewsState()
        if let _ = error {
            LoaderView.hide()
            showMessage(title: "Get Key Error", message: error?.localizedDescription ?? "")
        } else {
            LoaderView.show("Connecting")
            print("Key received, proceed to connect")
            terminal.connect()
        }
    }
    
    func bleTerminalDidConnect(terminal: BleTerminal, error: BleConnectionError?) {
        if let _ = error {
            showMessage(title: "Connection Error", message: error?.localizedDescription ?? "")
        }
        updateViewsState()
        LoaderView.hide()
    }
    
    func bleTerminalDidAction(terminal: BleTerminal, action: BleAction, error: BleActionError?) {
        
        if let error = error {
            showMessage(title: "Action Failed", message: "[\(action)] \(error.localizedDescription)")
        } else {
            switch action {
            case .lock:
                showMessage(title: "Action", message: "Lock Action Success\nLock state: [\(terminal.lockState)]")
            case .unlock:
                showMessage(title: "Action", message: "Unlock Action Success\nLock state: [\(terminal.lockState)]")
            case .horn:
                showMessage(title: "Action", message: "Horn Action Success")
            case .headlight:
                showMessage(title: "Action", message: "Headlight Action Success")
            case .lockState:
                showMessage(title: "Action", message: "Vehicle's door is \(terminal.lockState)")
            @unknown default:
                break
            }
        }
        self.updateViewsState()
        LoaderView.hide()
    }
    
    func bleTerminalDisconnected(terminal: BleTerminal) {
        showMessage(title: "", message: "Disconnected")
        self.updateViewsState()
        rssiLabel.text = ""
        LoaderView.hide()
    }
    
    func bleTerminalSignalUpdate(rssi: Int, strength: BleSignalStrength) {
        rssiLabel.text = "RSSI: \(rssi) dBm (\(strength))"
    }

    
}

class LoaderView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        let activityIndicator = UIActivityIndicatorView(style: .whiteLarge)
        activityIndicator.backgroundColor = UIColor.black.withAlphaComponent(0.7)
        activityIndicator.frame = frame
        addSubview(activityIndicator)
        activityIndicator.startAnimating()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public static func show(_ text: String = "") {
        hide()
        let window = UIApplication.shared.keyWindow!
        let loaderView = LoaderView(frame: window.bounds)
        let label = UILabel(frame: window.bounds)
        label.text = text
        label.transform = CGAffineTransform(translationX: 0, y: 40)
        label.textAlignment = .center
        label.textColor = .white
        loaderView.addSubview(label)
        window.addSubview(loaderView)
    }
    
    public static func hide() {
        if let window = UIApplication.shared.keyWindow, let loaderView = window.subviews.first(where: { $0 is LoaderView}) {
            loaderView.removeFromSuperview()
        }
    }
    
}

