package com.sonic.cow.client.impl;

import com.alibaba.fastjson.JSON;
import com.mashape.unirest.http.Headers;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.sonic.cow.client.TtsV2Client;
import com.sonic.cow.client.config.TtsConfig;
import com.sonic.cow.domain.input.VoiceTtsV2Input;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.Base64;
import java.util.Set;

@Slf4j
@Service
public class TtsV2ClientImpl implements TtsV2Client {

    @Autowired
    private TtsConfig ttsConfig;
    /**
     * 资源ID
     */
    private static final String resourceId = "volc.megatts.default";
    /**
     * 请求地址
     */
    private static final String url = "https://voice.ap-southeast-1.bytepluses.com/api/v3/tts/unidirectional";

    @Override
    public String tts(String userId, VoiceTtsV2Input input) {
        HttpResponse<InputStream> response;
        try {
            // additions
            JSONObject additions = new JSONObject();
            additions.put("disable_markdown_filter", true);
            additions.put("enable_language_detector", true);
            additions.put("enable_latex_tn", true);
            additions.put("disable_default_bit_rate", true);
            additions.put("max_length_to_filter_parenthesis", 0);
            JSONObject cacheConfig = new JSONObject();
            cacheConfig.put("text_type", 1);
            cacheConfig.put("use_cache", false);
            additions.put("cache_config", cacheConfig);
            String additionsJson = additions.toString();

            // payload
            JSONObject payload = new JSONObject();
            JSONObject user = new JSONObject();
            user.put("uid", userId);
            payload.put("user", user);
            JSONObject reqParams = new JSONObject();
            reqParams.put("text", input.getText());
            reqParams.put("speaker", input.getVoiceType());
            reqParams.put("additions", additionsJson);
            JSONObject audioParams = new JSONObject();
            audioParams.put("format", "mp3");
            audioParams.put("sample_rate", 24000);
            //设置语速
            audioParams.put("speech_rate", input.getSpeechRate());

            //设置音高
            JSONObject postProcess = new JSONObject();
            postProcess.put("pitch", input.getPitchRate());
            audioParams.put("post_process", postProcess);

            reqParams.put("audio_params", audioParams);
            payload.put("req_params", reqParams);

            log.info("===> tts param : {}", payload);

            // request
            response = Unirest.post(url)
                    .header("X-Api-App-Id", ttsConfig.getTtsAppId())
                    .header("X-Api-Access-Key", ttsConfig.getTtsAccessToken())
                    .header("X-Api-Resource-Id", resourceId)
                    .header("X-Api-App-Key", "aGjiRDfUWi")
                    .header("Content-Type", "application/json")
                    .header("Connection", "keep-alive")
                    .body(payload.toString())
                    .asBinary();
            Headers headers = response.getHeaders();
            log.info("===> tts response headers: {}", JSON.toJSONString(headers));
            // process stream
            try (InputStream is = response.getBody();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {

                ByteArrayOutputStream audioData = new ByteArrayOutputStream();
                int totalAudioSize = 0;
                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.isEmpty()) {
                        continue;
                    }
                    JSONObject data = new JSONObject(line);
                    log.info("json data:{}", JSON.toJSONString(data));

                    int code = data.optInt("code", 0);
                    if (code == 0) {
                        if (data.has("data") && !data.isNull("data") && !data.getString("data").isEmpty()) {
                            byte[] chunkAudio = Base64.getDecoder().decode(data.getString("data"));
                            int audioSize = chunkAudio.length;
                            totalAudioSize += audioSize;
                            audioData.write(chunkAudio);
                        }
                    } else if (code == 20000000) {
                        break;
                    } else if (code > 0) {
                        log.info("error response:" + data);
                        break;
                    }
                }

                // save audio data to local file
                if (audioData.size() > 0) {

                    String audioDataBase64 = Base64.getEncoder().encodeToString(audioData.toByteArray());
                    log.info("==================================");
                    log.info(audioDataBase64);
                    log.info("==================================");
                    return audioDataBase64;
                }
            }
        } catch (UnirestException | IOException e) {
            log.error("===> request error: ", e);
        }
        return null;
    }

}
