# coding=utf-8
import sys
import json
import base64
import requests
import webbrowser
import wave
import pyaudio
import os
import time
import ybc_config

__PREFIX = ybc_config.config['prefix']
__TTS_URL = __PREFIX + ybc_config.uri + '/text2voice'
__ASR_URL = __PREFIX + ybc_config.uri + '/speech'

__RATE = 16000
__FORMAT_TYPE = 2
__SECONDS = 5
__TO_DIR = None
__CHANNELS = 1
__CHUNK = 1024
__SPEAKER = 1
__SPEED = 1
__AHT = 0
__APC = 58
__VOLUME = 10
__FORMAT = 2


def voice2text(filename='', rate=__RATE, format_type=__FORMAT_TYPE):
    """
    功能：把语音文件转换成文字。

    参数 filename 是当前目录下期望转换成文字的语音文件的名字，

    可选参数 rate 是语音文件的采样率，1 代表 16000，0 代表 8000，默认为 1，

    可选参数 format_type 是语音文件的类型，默认 PCM 格式，

    返回：转换成的文字。
    """

    if not filename:
        return -1

    if rate in (0, 1, 8000, 16000):
        rate = 1
    else:
        rate = 1

    if format_type not in (1, 2, 3, 4):
        format_type = 'PCM'
    else:
        format_type = 'PCM'

    url = __ASR_URL
    filepath = os.path.abspath(filename)
    data = {}
    data['format'] = format_type
    data['sampleRate'] = rate
    files = {
        'file': open(filepath, 'rb')
    }

    for i in range(3):
        r = requests.post(url, data=data, files=files)
        if r.status_code == 200:
            res = r.json()
            return res['data']
        elif i < 2:
            continue
        else:
            raise ConnectionError('转换语音文件失败', r._content)


def record(filename, seconds=__SECONDS, to_dir=__TO_DIR, rate=__RATE, channels=__CHANNELS, chunk=__CHANNELS):
    """
    功能：录制音频文件。

    参数 filename 是录制生成的语音文件的名字，

    可选参数 seconds 是录制时长（单位：秒），默认 5 秒，

    可选参数 to_dir 是存放语音文件的目录，默认为当前目录，

    可选参数 rate 是录制采样率，1 代表 16000，0 代表 8000，默认为 1，

    可选参数 channels 是声道，默认 1，

    可选参数 chunk 是一次读取的字节数，默认 1024，

    返回：录制的音频文件的路径。
    """
    if not filename:
        return -1

    if to_dir is None:
        to_dir = "./"

    if not isinstance(seconds, int) or seconds <= 0:
        raise ValueError('录制时长必须为正整数！')

    pa = pyaudio.PyAudio()
    stream = pa.open(format = pyaudio.paInt16,
                     channels = channels,
                     rate = rate,
                     input = True,
                     frames_per_buffer = chunk)

    print("* 开始录制")

    save_buffer = []
    for i in range(0, int(rate / chunk * seconds)):
        audio_data = stream.read(chunk)
        save_buffer.append(audio_data)

    print("* 结束录制")

    # stop
    stream.stop_stream()
    stream.close()
    pa.terminate()

    if to_dir.endswith('/'):
        file_path = to_dir + filename
    else:
        file_path = to_dir + "/" + filename

    # save file
    wf = wave.open(file_path, 'wb')
    wf.setnchannels(channels)
    wf.setsampwidth(pa.get_sample_size(pyaudio.paInt16,))
    wf.setframerate(rate)
    # join 前的类型
    wf.writeframes(b''.join(save_buffer))
    wf.close()

    return file_path


def text2voice(text, filename, speaker=__SPEAKER, speed=__SPEED, aht=__AHT, apc=__APC, volume=__VOLUME, _format=__FORMAT, rate=__RATE):
    """
    功能：把文字转换成语音。

    参数 text 是待转换的文字，

    参数 filename 是生成的语音文件的名字，

    可选参数 speaker 是发音人，1 代表小刚（男声），2 代表小云（女声），默认为1，

    可选参数 speed 是语速，1 代表正常速度，0.5 代表慢速，2 代表快速，默认为1，

    可选参数 aht 是音高，默认为 0，

    可选参数 apc 是音色，默认为 58，

    可选参数 volume 是音量，默认为 10，

    可选参数 _format 是语音文件的格式，1 代表 PCM，2 代表 WAV，3代表 MP3，默认为 2 ，

    可选参数 rate 是语音采样率，1 代表 16000，0 代表 8000，默认为 1，

    返回：生成的语音文件的名字。
    """
    if not filename or not text:
        return -1

    if speaker == 1:
        speaker = 'xiaogang'
    elif speaker == 2:
        speaker = 'xiaoyun'
    else:
        speaker = 'xiaogang'

    if speed == 1:
        speed = 0
    elif speed == 0.5:
        speed = -250
    elif speed == 1.5:
        speed = 250
    elif speed == 2:
        speed = 500
    else:
        speed = 0

    if _format == 2:
        _format = 'WAV'
    elif _format == 1:
        _format = 'PCM'
    elif _format == 3:
        _format = 'MP3'
    else:
        _format = 'WAV'

    if rate in (0, 1, 8000, 16000):
        rate = 1
    else:
        rate = 1

    url = __TTS_URL

    data = {}
    data['text'] = text
    data['voice'] = speaker
    data['format'] = _format
    data['sampleRate'] = rate
    data['volume'] = volume
    data['speechRate'] = speed
    data['pitchRate'] = aht

    headers = {'content-type': "application/json"}

    for i in range(3):
        r = requests.post(url, json=data, headers=headers)
        if r.status_code == 200:
            res = r.json()

            b64_data = base64.b64decode(res['data'])
            with open(filename, 'wb') as f:
                f.write(b64_data)
            return filename
        elif i < 2:
            continue
        else:
            raise ConnectionError('获取音频失败，无法播放', r._content)



def speak(text='', speaker=__SPEAKER, speed=__SPEED, aht=__AHT, apc=__APC):
    """
    功能：朗读一段文字。

    参数 text 是待朗读的文字，

    可选参数 speaker 是发音人，1 代表小刚（男声），2 代表小云（女声），默认为1，

    可选参数 speed 是语速，1 代表正常速度，0.5 代表慢速，2 代表快速，默认为1，

    可选参数 aht 是音高，默认为 0，

    可选参数 apc 是音色，默认为 58，

    返回：无。
    """
    if text:
        filename = str(int(time.time())) + '_tmp.wav'
        res1 = text2voice(text, filename, speaker, speed, aht, apc)
    os.system(filename)
    if len(text) <= 10:
        time.sleep(4)
    elif len(text) <= 20:
        time.sleep(5)
    elif len(text) <= 30 :
        time.sleep(6)
    elif len(text) <= 40 :
        time.sleep(7)



def main():
    # text2voice('猿辅导你好', 'test.wav')
    # voice2text('test.wav')
    speak('猿辅导你好')


if __name__ == '__main__':
    main()