//
//  ViewController.swift
//  HARKlibSample
//
//  Created by Tomoyoshi Kinoshita on 2021/04/15.
//

import UIKit
import AVFoundation
import HARKlib

class ViewController: UIViewController {

    let audioManager = AudioManager()
    let harkNetwork: HARKNetwork = HARKNetwork.create(Main.self, name: "MAIN")
    var audioManagerPrepared: Bool = false
    
    @IBOutlet weak var switchStatus: UISwitch!
    @IBOutlet weak var textView: UITextView!
    @IBOutlet weak var _statusTextField: UITextField!
    var _last_sources = Set<Int>()
    
    let background_queue = DispatchQueue.init(label: "background")
    
    enum RecognitionState: String
    {
        case idle = "IDLE"
        case working = "WORKING"
        case error = "ERROR"
    }
    var _recognition_state: RecognitionState = .idle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
//        self.harkNetwork.build()
        
        if let subscriber_node = self.harkNetwork.query_node("Subscriber") as? HARKlib.SubscribeData {
            subscriber_node.delegate = self
        }
        if let subscriber_node = self.harkNetwork.query_node("Subscriber_Source") as? HARKlib.SubscribeData {
            subscriber_node.delegate = self
        }

        self.set_recognition_status(.idle)
    }
    
    func set_recognition_status(_ state: RecognitionState)
    {
        switch(state){
        case .idle:
            self._statusTextField.text = state.rawValue
        case .working:
            self._statusTextField.text = state.rawValue
        default:
            return
        }
        self._recognition_state = state
    }

    @IBAction func onSwitchValueChanged(_ sender: Any) {
        if let sw = sender as? UISwitch {
            if sw.isOn {
                self.start_recognition()
            }else{
                self.stop_recognition()
            }
        }
    }

    func start_recognition()
    {
        if self._recognition_state != .working {
            if !self.audioManagerPrepared {
                self.audioManager.prepare(handler: self.receiveAudio, bufferSize: 1600)
                self.audioManagerPrepared = true
            }
            self.audioManager.start()
            self.background_queue.async {
                self.harkNetwork.execute()
            }
            
            self.set_recognition_status(.working)
        }
    }

    func stop_recognition()
    {
        if self._recognition_state != .idle {
            self.audioManager.stop()
            self.harkNetwork.stop()

            self.set_recognition_status(.idle)
        }
    }
    
    func receiveAudio(buffer: AVAudioPCMBuffer) {
//        print(buffer.int16ChannelData!.pointee.pointee)
//        let p = UnsafeBufferPointer<Float>(start: buffer.floatChannelData!.pointee, count: Int(buffer.frameLength))
        let p = UnsafeBufferPointer<Int16>(start: buffer.int16ChannelData!.pointee, count: Int(buffer.frameLength))
//        print("count: \(buffer.frameLength)")

        var s: Double = 0.0
        for v in p {
            let dv: Double = Double(v)
            s += dv * dv
        }
        s /= Double(p.count)
        
//        print(sqrt(s))
        
        if let publisher_node = self.harkNetwork.query_node("Publisher") as? HARKlib.PublishData {
            publisher_node.pushInt16Vector(p.baseAddress!, count: p.count)
            NSLog("pushed");
        }else{
            NSLog("publisher not found");
        }
    }
    
}

extension ViewController: HARKlib.SubscribeDataDelegate
{
    func receive(_ value: NSObject) {
        if let dict = value as? NSDictionary {
            var new_dict = Set<Int>()
            for (id, _) in dict {
                new_dict.insert(id as! Int)
            }
	
            var appeared = new_dict.subtracting(self._last_sources)
            var disappeared = self._last_sources.subtracting(new_dict)
            
            for ap in appeared {
                DispatchQueue.main.async {
                    var t = self.textView.text + "Found: \(ap)\n"
                    self.textView.text = t
                }
//                NSLog("Appeared: \(ap)")
            }
            for da in disappeared {
                DispatchQueue.main.async {
                    var t = self.textView.text + "Lost:  \(da)\n"
                    self.textView.text = t
                }
//                NSLog("Disappeared: \(da)")
            }
                
            self._last_sources = new_dict

        }else if let arr = value as? NSArray {
            for elem in arr {
                if let source = elem as? Source {
//                    NSLog("Source: \(source)")
                }
            }
        }
    }
}

extension ViewController: UITextViewDelegate
{
    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        return true
    }
}
