# -*- coding: utf-8 -*-
import os
import sys
import time
import wave
import socket
import pyaudio
import logging
import threading

WAV_MAX_CHUNK_SIZE = 1024 * 1000 * 1000 * 1000 * 1000 * 1000  # 1024PB
MP4_FRAME_SECONDS = (1000.0 / 25.0) / 1000.0

exe_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
xusb_path = os.path.join(exe_dir, 'xusb.bat')
blank_wav_path = os.path.join(exe_dir, 'blank.wav')

play_index = 0
play_start_t = 0
play_error_t = 0


def init_wav_player() -> tuple:
    """初始化wav音频播放器
    """

    wav_player = pyaudio.PyAudio()
    wav_stream = wav_player.open(format=pyaudio.paInt16, channels=2, rate=48000, frames_per_buffer=0, output=True)

    # 播放空白音频，激活播放器，避免开播后激活造成耗时
    with open(blank_wav_path, 'rb') as f:
        wav_stream.write(f.read())

    time.sleep(1)
    return wav_player, wav_stream


def handle_update_frame(sock: socket.socket):
    """处理摄像头推流
    """

    frame_index = 0
    while True:
        # 发送当前帧
        frame_path = os.path.join(exe_dir, 'frame', f'{frame_index}.jpg')
        sock.sendall(frame_path.encode() + b'\0')

        # 等待切换下一帧
        while frame_index == true_index():
            time.sleep(0.002)

        # 切换到下一帧
        frame_index = true_index()


def true_index():
    """返回当前应该播放的帧序号
    """

    return int((time.time() - play_start_t + play_error_t) / MP4_FRAME_SECONDS)


def update_xusb_frame():
    """摄像头推流
    """

    # 启动xusb
    os.system(f'start {xusb_path}')
    time.sleep(5)
    while True:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            sock.connect(('127.0.0.1', 9029))
            handle_update_frame(sock)
        except Exception as e:
            try:
                sock.close()
            except Exception:
                pass
            logging.error(f'摄像头推流异常，5s后重新建立xusb连接：{e}')
            # 重启xusb
            os.system(f'start {xusb_path}')
            time.sleep(5)


def play_wav():
    """wav播放
    """

    global play_start_t, play_error_t, play_index
    # 初始化wav播放器
    wav_player, wav_stream = init_wav_player()
    play_start_t = time.time()
    while True:
        wav_path = os.path.join(exe_dir, 'wav', f'{play_index}.wav')
        if os.path.exists(wav_path):
            logging.error(f'播放{wav_path}')
            try:
                with wave.open(wav_path, 'rb') as wf:
                    wav_stream.write(wf.readframes(WAV_MAX_CHUNK_SIZE))

            except Exception as e:
                logging.error(f'{wav_path}播放失败，等待30秒 {e}')
                # 重新初始化wav播放器
                wav_player, wav_stream = init_wav_player()
                time.sleep(30)

        # 片段不存在，等待一轮
        else:
            logging.error(f'{wav_path}不存在，等待30秒')
            time.sleep(30)

        # 播放完毕
        play_error_t = (time.time() - play_start_t) - (play_index + 1) * 30

        logging.error(f'{wav_path}播放完毕')
        play_index += 1


if __name__ == '__main__':
    """RTMP_VCAM
    """

    logging.error('进入准备阶段，等待40秒')
    time.sleep(40)
    logging.error('准备就绪')

    # 摄像头推流
    threading.Thread(target=update_xusb_frame).start()

    # wav播放
    threading.Thread(target=play_wav).start()

    time.sleep(5)
    ret = 0
    while True:
        time.sleep(30)
        logging.error(f'清理{ret}.wav')
        try:
            os.remove(os.path.join(exe_dir, 'wav', f'{ret}.wav'))
        except Exception:
            pass
        for i in range(750):
            try:
                os.remove(os.path.join(exe_dir, 'frame', f'{ret * 750 + i + 1}.jpg'))
            except Exception:
                pass
        ret += 1
