import os
import json
import time
import threading
import librosa
import numpy as np
import random

import base
import rest
from config import cfg

from actuator import Actuator


TALK_ACTION_FOLDER = cfg.get("talk", "actionfd")


_talkthreadsinglelock = False

class _talkthread(threading.Thread):
    def __init__(self, token, title, index):
        self.running = False
        self.acting = False
        self.token = token
        self.title = title
        self.curactindex = index
                
        threading.Thread.__init__(self)

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

        actiondir = os.path.join(TALK_ACTION_FOLDER, self.title+".json")
        with open(actiondir, 'r') as f:
            actions = json.load(f)
            usedtime = 0
            while self.curactindex < len(actions) and self.running:
                starttime = time.time()
                
                a = actions[self.curactindex]
                time.sleep(a["time"]-usedtime)
                self._doact(a["action"], a["duration"])
                self.curactindex += 1
                
                stoptime = time.time()
                usedtime = usedtime + stoptime - starttime
        
        self.running = False    # for break
        _talkthreadsinglelock = False

    
    def _doact(self, action, duration):
        match action:
            case "f":
                Actuator.ForwardByTime(self.token, duration)
            case "b":
                Actuator.BackwardByTime(self.token, duration)
            case "l":
                Actuator.LeftByTime(self.token, duration)
            case "r":
                Actuator.RightByTime(self.token, duration)
            case "lf":
                Actuator.LeftForwardByTime(self.token, duration)
            case "lb":
                Actuator.LeftBackwardByTime(self.token, duration)
            case "rf":
                Actuator.RightForwardByTime(self.token, duration)
            case "rb":
                Actuator.RightBackwardByTime(self.token, duration)

    
    def IsRunning(self):
        return _talkthreadsinglelock
        

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

    def GetCurActIndex(self):
        return self.curactindex
       



class _talk:
    def __init__(self):
        self.talkthread = None

    
    def GetTitles(self):
        titles = []
        for root, dirs, files in os.walk(TALK_ACTION_FOLDER):
            for f in files:
                if f.endswith(".json"):
                    titles.append(f[:(len(f)-5)])
        return titles

    
    def GetTitleTimes(self, title):
        times = [0]
        
        actiondir = os.path.join(TALK_ACTION_FOLDER, title+".json")
        with open(actiondir, 'r') as f:
            actions = json.load(f)
            actioncount = len(actions)
            if actioncount < 1 :
                return None
                
            for a in actions:
                times.append(a["time"])
                
            lasta = actions[actioncount-1]
            times.append(lasta["time"]+lasta["duration"])
        
        return times
        
    
    def GetActInfo(self):
        if self.talkthread is None :
            return {"index": -1}
        
        return {"index": self.talkthread.GetCurActIndex()}


    def StartAct(self, token, title, index):
        if self.talkthread is not None:
            if self.talkthread.IsRunning() :
                return False

        self.talkthread = _talkthread(token, title, index)
        self.talkthread.start()
        return True
        
        
    def StopAct(self, token):
        if self.talkthread is not None:
            if self.talkthread.IsRunning():
                self.talkthread.StopThread()
        
        return True
        
        
Talk = _talk()
