import json
import time
import threading

from pypinyin import lazy_pinyin

import base
import rest
from config import cfg
from actuator import Actuator, ONE_MOVE_DURATION, ONE_TINYTURN_DURATION
from audio import AudioController

SENTENCEMAXTIME = cfg.getfloat("listen", "sentencemaxtime")           # s, max time of one sentence 
EMPTYMAXCOUNT = cfg.getint("listen", "emptymaxcount")               # max empty sentences count for non-sleeping
RECORD_SENTENCE_DIR = "/mdata/sentence.wav"
RESPONSE_IAM_DIR = "/conf/voice/iam.wav"
RESPONSE_OK_DIR = "/conf/voice/ok.wav"
RESPONSE_NO_DIR = "/conf/voice/no.wav"
RESPONSE_RESET_DIR = "/conf/voice/reset.wav"

_listenthreadsinglelock = False   # just one video thread can be run

class _listenthread(threading.Thread):
    def __init__(self, token):
        threading.Thread.__init__(self)
        self.running = False
        self.acting = False
        self.token = token

        self.currenttext = ""

    
    def run(self):
        global _listenthreadsinglelock
        if _listenthreadsinglelock :
            return
        _listenthreadsinglelock = True
        self.running = True

        hr = AudioController.OpenMic(self.token)
        if hr: 
            while self.running :
                hr = AudioController.Record(self.token, True, RECORD_SENTENCE_DIR, SENTENCEMAXTIME)
                if hr: 
                    (hr, resp) = AudioController.Recognize(self.token, RECORD_SENTENCE_DIR)
                    if hr:
                        self.currenttext = resp
                        pinyinlist = lazy_pinyin(resp)
                        pinyin = ''.join(pinyinlist)
                        if "liang" in pinyin :
                            hr = AudioController.Play(self.token, RESPONSE_IAM_DIR)
                            if hr : 
                                self.acting = True
                                self._doaction()
                        
        if not AudioController.CloseMic(self.token):
            print("Zhi Error: Close recorder error")
            
        self.running = False    # for break
        _listenthreadsinglelock = False
        
                                
    def _doaction(self):
        emptycount = 0
        while self.acting and self.running :
            hr = AudioController.Record(self.token, True, RECORD_SENTENCE_DIR, SENTENCEMAXTIME)
            if hr: 
                (hr, resp) = AudioController.Recognize(self.token, RECORD_SENTENCE_DIR)
                if hr:
                    self.currenttext = resp
                    emptycount = 0
                    pinyinlist = lazy_pinyin(resp)
                    pinyin = ''.join(pinyinlist)
                    if "qian" in pinyin :
                        AudioController.Play(self.token, RESPONSE_OK_DIR)
                        Actuator.Forward(self.token)
                        time.sleep(ONE_MOVE_DURATION)
                    elif "hou" in pinyin :
                        AudioController.Play(self.token, RESPONSE_OK_DIR)
                        Actuator.Backward(self.token)
                        time.sleep(ONE_MOVE_DURATION)
                    elif "zuo" in pinyin :
                        AudioController.Play(self.token, RESPONSE_OK_DIR)
                        Actuator.Left(self.token)
                        time.sleep(ONE_TINYTURN_DURATION)
                    elif "you" in pinyin :
                        AudioController.Play(self.token, RESPONSE_OK_DIR)
                        Actuator.Right(self.token)
                        time.sleep(ONE_TINYTURN_DURATION)
                    else :
                        AudioController.Play(self.token, RESPONSE_NO_DIR)
            else:
                emptycount += 1
                if emptycount > EMPTYMAXCOUNT :
                    break
                    
        self.acting = False
        AudioController.Play(self.token, RESPONSE_RESET_DIR)
          
    
    def IsRunning(self):
        return _listenthreadsinglelock

    
    def StopThread(self):
        self.running = False
        while(self.is_alive()):
            time.sleep(1)

    
    def GetCurrentText(self):
        text = self.currenttext
        self.currenttext = ""
        return {"text": text}
        

class _listen:
    def __init__(self):
        self.listenthread = None
        
    def StartListen(self, token):
        if self.listenthread is not None:
            if self.listenthread.IsRunning() :
                return False

        self.listenthread = _listenthread(token)
        self.listenthread.start()
        return True
        
        
    def StopListen(self):
        if self.listenthread is not None:
            if self.listenthread.IsRunning():
                self.listenthread.StopThread()
        
        return True

    
    def GetCurrentText(self):
        if self.listenthread is not None:
            if self.listenthread.IsRunning():
                return self.listenthread.GetCurrentText()
                
        return None
        

Listen = _listen()
