package com.zd.speaker.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.redis.service.RedisService;
import com.zd.speaker.domain.RemoteAddress;
import com.zd.speaker.domain.vo.PlayBatchVo;
import com.zd.speaker.domain.vo.PlayVo;
import com.zd.speaker.domain.vo.UrlVo;
import com.zd.speaker.service.ISpeakerService;
import com.zd.speaker.utils.OkHttpRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 电话报警推送日志Service业务层处理
 *
 * @author donggaosheng
 * @date 2021-11-11
 */
@Service
@RefreshScope
public class SpeakerServiceImpl implements ISpeakerService {

    @Value("${speaker.port:8888}")
    private String port;

    @Value("${speaker.isOnline:0}")
    private Integer isOnline;


    private static Logger logger = LoggerFactory.getLogger(SpeakerServiceImpl.class);
    @Autowired
    private OkHttpRequest okHttpRequest;

    @Autowired
    private RemoteAddress remoteAddress;

    @Autowired
    private RedisService redisService;


    @Override
    public String getToken() {
        String token = redisService.getCacheObject("token");
        if (StringUtils.isNotEmpty(token) && StringUtils.isNotBlank(token)) {
            return token;
        }
        String tokenStr = login();
        redisService.setCacheObject("token", tokenStr, 60L, TimeUnit.DAYS);
        logger.info(tokenStr);
        return tokenStr;
    }

    @Override
    public void setToken() {
        String tokenStr = login();
        redisService.setCacheObject("token", tokenStr, 60L, TimeUnit.DAYS);
    }

    @Override
    public String login() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("email", "ls20@admin");
        jsonObject.put("password", "admin");
        JSONObject jsonUser = new JSONObject();
        jsonUser.put("user", jsonObject);
        String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getRemoteIp() + ":" + remoteAddress.getRemotePort() + remoteAddress.getLoginUrl();
        String responseStr = okHttpRequest.doPostJson(remoteUrl, jsonUser.toString());
        JSONObject responseJson = JSONObject.parseObject(responseStr);
        JSONObject userJson = responseJson.getJSONObject("user");
        String tokenStr = userJson.getString("token");
        return tokenStr;
    }

    @Override
    public String getDeviceList(Integer page, Integer pageSize) {
        Map<String, Object> jsonObject = new HashMap<>();
        jsonObject.put("page", page);
        jsonObject.put("pageSize", pageSize);
        String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getRemoteIp() + ":" + remoteAddress.getRemotePort() + remoteAddress.getDeviceUrl();
        String token = getToken();
        String[] strings = new String[]{"Authorization", "Bearer " + token};
        String requestStr = okHttpRequest.doGet(remoteUrl, jsonObject, strings);
        boolean isTrue = tokenRefresh(requestStr);
        if (isTrue) {
            return getDeviceList(page, pageSize);
        }
        return requestStr;
    }

    @Override
    public String getDevice(String deviceId) {
        String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getRemoteIp() + ":" + remoteAddress.getRemotePort() + remoteAddress.getDeviceUrl() + "/" + deviceId;
        String token = getToken();
        String[] strings = new String[]{"Authorization", "Bearer " + token};
        String requestStr = okHttpRequest.doGet(remoteUrl, strings);
        boolean isTrue = tokenRefresh(requestStr);
        if (isTrue) {
            return getDevice(deviceId);
        }
        return requestStr;
    }

    @Override
    public String playMusic(String ip, String body) {
        String remoteUrl = remoteAddress.getProtocol() + "://" + ip + ":" + port;
        String token = getToken();
        String responseStr = okHttpRequest.doPostJson(remoteUrl, token, body);
        boolean isTrue = tokenRefresh(responseStr);
        if (isTrue) {
            return playMusic(ip, body);
        }
        return responseStr;
    }

    @Override
    public String textParseVoice(String ip, List<String> texts, PlayVo playVo) {
        List<UrlVo> urlVoList = new ArrayList<>();
        for (String text : texts) {
            UrlVo urlVo = new UrlVo();
            urlVo.setName(text.substring(0, 8));
            String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getTtsPort() + "/tts_xf.single?text=" + text + "&voice_name=xiaoyan&speed=" + playVo.getSpeed() + "&volume=" + playVo.getParams().getVol();
            urlVo.setUri(remoteUrl);
            urlVoList.add(urlVo);
        }
        if (null != playVo.getParams()) {
            playVo.getParams().setUrls(urlVoList);
        }
        String body = JSONObject.toJSON(playVo).toString();
        String remoteUrl = remoteAddress.getProtocol() + "://" + ip + ":" + port;
        String token = getToken();
        String responseStr = okHttpRequest.doPostJson(remoteUrl, token, body);
        boolean isTrue = tokenRefresh(responseStr);
        if (isTrue) {
            return textParseVoice(ip, texts, playVo);
        }
        return responseStr;
    }

    @Override
    public String textParseVoiceURL(Integer speed, Integer volume, String text) {
        String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getTtsPort() + "/tts_xf.multi";
        String token = getToken();
        String[] strings = new String[]{"Authorization", "Bearer " + token};
        Map<String, Object> map = new HashMap<>();
        map.put("text", text);
        map.put("voice_name", "xiaoyan");
        map.put("speed", speed);
        map.put("volume", volume);
        map.put("origin", remoteUrl.replace("/tts_xf.multi", ""));
        String responseStr = okHttpRequest.doGet(remoteUrl, map, strings);
        boolean isTrue = tokenRefresh(responseStr);
        if (isTrue) {
            return textParseVoiceURL(speed, volume, text);
        }
        return responseStr;
    }

    @Override
    public void textParseVoiceIps(String texts, List<PlayVo> playVoList) {
        commonTextParseVoice(texts,playVoList);
    }

    @Override
    public void textParseVoiceAppIps(String texts,List<PlayVo> playVoList) {
        if (playVoList.size() == 1) {
            commonTextUrlVoice(texts, playVoList);
        } else {
            PlayBatchVo playBatchVo = new PlayBatchVo();
            BeanUtils.copyProperties(playVoList.get(0), playBatchVo);
            List<UrlVo> urlVoList = getUrlList(texts);
            if (null != playBatchVo.getParams()) {
                playBatchVo.getParams().setTid(UUID.randomUUID().toString());
                playBatchVo.getParams().setUrls(urlVoList);
            }
            List<String> snsList = new ArrayList<>();
            for (PlayVo playVo : playVoList) {
                snsList.add(playVo.getSn());
            }
            String deviceIp =playVoList.get(0).getDeviceIp();
            playBatchVo.setSns(snsList.toArray(new String[snsList.size()]));
            boolean isTrue = invokePost(JSONObject.toJSON(playBatchVo).toString(), deviceIp,1, playVoList.get(0).getPort());
            if (isTrue) {
                textParseVoiceAppIps(texts,playVoList);
            }
        }
    }

    @Override
    public void textParseUrlAppIpsOrigin(String text,List<PlayVo> playVo) {
        commonTextParseVoice(text,playVo);
    }

    @Override
    public boolean stopPlayMusic(String sn, String ip) {
        logger.info("********************" + sn + "********************");
        String remoteUrlIp = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getRemotePort() + "/api/sendtodevice";
        String token = getToken();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sn", sn);
        jsonObject.put("type", "req");
        jsonObject.put("name", "songs_queue_clear");
        String responseStr = okHttpRequest.doPostJson(remoteUrlIp, token, jsonObject.toString());
        logger.info("responseStr:+++++++++++++++++++++++++++" + responseStr + "+++++++++++++++++++++++++");
        return tokenRefresh(responseStr);
    }

    /**
     * 认证失败刷新token
     * @param requestStr
     * @return
     */
    private boolean tokenRefresh(String requestStr) {
        JSONObject responseJson = JSONObject.parseObject(requestStr);
        if (StringUtils.isNotNull(responseJson) && StringUtils.isNotNull(responseJson.getInteger("code")) && responseJson.getInteger("code") == 401) {
            setToken();
            return true;
        }
        return false;
    }

    private List<UrlVo> getUrlList(String texts) {
        List<UrlVo> urlVoList = new ArrayList<>();
        UrlVo urlVo = new UrlVo(texts.substring(0, 1), texts);
        urlVoList.add(urlVo);
        return urlVoList;
    }

    private List<UrlVo> getTextParseUrl(String text,PlayVo playVo) {
        List<UrlVo> urlVoList = new ArrayList<>();
        String remoteUrl = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getTtsPort() + "/tts_xf.single?text=" + text + "&voice_name=xiaoyan&speed=" + playVo.getSpeed() + "&volume=" + playVo.getParams().getVol();
        UrlVo urlVo = new UrlVo(text.substring(0, 1), remoteUrl);
        urlVoList.add(urlVo);
        return urlVoList;
    }

    /**
     * 公共的文字转语音播放
     *
     * @param texts
     * @param playVoList
     */
    private void commonTextParseVoice(String texts,List<PlayVo> playVoList) {
        for (PlayVo play : playVoList) {
            String deviceIp=play.getDeviceIp();
            List<UrlVo> urlVoList = getTextParseUrl(texts,play);
            if (null != play.getParams()) {
                play.getParams().setTid(UUID.randomUUID().toString());
                play.getParams().setUrls(urlVoList);
            }
            boolean isTrue = invokePost(JSONObject.toJSON(play).toString(),deviceIp, 0, play.getPort());
            if (isTrue) {
                commonTextParseVoice(texts,playVoList);
                break;
            }
        }
    }


    /**
     * 公共的语音路径播放
     * commonTextUrlVoice
     * @param texts
     * @param playVoList
     */
    private void commonTextUrlVoice(String texts,List<PlayVo> playVoList) {
        for (PlayVo play : playVoList) {
            String deviceIp=play.getDeviceIp();
            List<UrlVo> urlVoList = getUrlList(texts);
            if (null != play.getParams()) {
                play.getParams().setTid(UUID.randomUUID().toString());
                play.getParams().setUrls(urlVoList);
            }
            boolean isTrue = invokePost(JSONObject.toJSON(play).toString(),deviceIp, 0, play.getPort());
            if (isTrue) {
                commonTextParseVoice(texts,playVoList);
                break;
            }
        }
    }

    /**
     * @param body
     * @param type 0是单个，1是批量
     */
    private boolean invokePost(String body,String deviceIp, Integer type, int port) {
        logger.info("+++++++++++++++++++++++++++" + body + "+++++++++++++++++++++++++");
        String remoteUrlIp = "";
        if(isOnline==1){
            if (type == 0) {
                remoteUrlIp = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getRemotePort();
            } else {
                remoteUrlIp = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getRemotePort() + "/api/sendtodevice";
            }
        }else{
            if (type == 0) {
                remoteUrlIp = remoteAddress.getProtocol() + "://" + deviceIp + ":" + port;
            } else {
                remoteUrlIp = remoteAddress.getProtocol() + "://" + remoteAddress.getTtsIp() + ":" + remoteAddress.getRemotePort() + "/api/sendtodevice";
            }
        }
        String token = getToken();
        String responseStr = okHttpRequest.doPostJson(remoteUrlIp, token, body);
        logger.info("responseStr:+++++++++++++++++++++++++++" + responseStr + "+++++++++++++++++++++++++");
        return tokenRefresh(responseStr);
    }
}
