/*
 * Copyright 2024 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include "servererror.h"
#include "util.h"

namespace {

const std::map<int, baidu_speech_server_error::EngineErrorCode> asrErrorCodeMap = {
    {4, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyRequest}},
    {6, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {14, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {17, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyRequest}},
    {18, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooFrequentRequest}},
    {19, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyRequest}},
    {100, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {110, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {111, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {3300, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {3301, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooLittleData}},
    {3302, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {3303, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::NoServerService}},
    {3304, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooFrequentRequest}},
    {3305, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyRequest}},
    {3307, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooLittleData}},
    {3008, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyData}},
    {3009, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {3010, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyData}},
    {3011, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {3012, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {3013, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {3014, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooLittleData}},
    {3015, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {3016, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}}};

const std::map<int, baidu_speech_server_error::EngineErrorCode> realtimeAsrErrorCodeMap = {
    {-3001, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {-3003, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {-3004, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {-3005, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooLittleData}},
    {-3006, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {-3008, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {-3011, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::FailedToConnectServer}},
    {-3012, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::FailedToConnectServer}},
    {-3013, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::ServerNoResponse}},
    {-3014, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::NoServerService}},
    {-3101, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooLittleData}},
    {-3102, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooManyData}}};

const std::map<int, baidu_speech_server_error::EngineErrorCode> ttsErrorCodeMap = {
    {500, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::NetworkLatencyTooLong}},
    {501, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {502, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {503, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {513, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {6, {ai_engine::EngineErrorCategory::Initialization, ai_engine::SpeechEngineErrorCode::Unauthorized}},
    {13, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooFrequentRequest}},
    {15, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::TooFrequentRequest}},
    {16, {ai_engine::EngineErrorCategory::InputError, ai_engine::SpeechEngineErrorCode::InvalidParamType}},
    {18, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::NoServerService}},
    {330, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::NoServerService}},
    {999, {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::NoServerService}}};
}; // namespace

int baidu_speech_server_error::parseErrorCode(const std::string &result) {
    Json::Value obj = baidu_speech_util::formatJsonFromString(result);
    if (!obj.isObject() || obj.isNull()) {
        return 0;
    }
    if (obj.isMember("error_code") && obj.isMember("error_msg")) {
        return obj["error_code"].asInt();
    }
    if (obj.isMember("err_msg") && obj.isMember("err_no")) {
        return obj["err_no"].asInt();
    }
    return 0;
}

void baidu_speech_server_error::parseErrorInfo(const std::string &result, int &errorCode, int &subErrorCode,
                                               std::string &errorMessage) {
    // 样例如下：
    // {
    //     "convert_offline":false,
    //     "err_detail":"110: Access token invalid or no longer valid",
    //     "err_msg":"110: Access token invalid or no longer valid",
    //     "err_no":502,
    //     "err_subcode":110,
    //     "tts_logid":3278535902
    // }
    Json::Value value = baidu_speech_util::stringToJson(result);
    if (value.isMember("err_no") && value["err_no"].isInt()) {
        errorCode = value["err_no"].asInt();
    }
    if (value.isMember("err_subcode") && value["err_subcode"].isInt()) {
        subErrorCode = value["err_subcode"].asInt();
    }
    if (value.isMember("err_msg") && value["err_no"].isString()) {
        errorMessage = value["err_msg"].asString();
    }
}

baidu_speech_server_error::EngineErrorCode baidu_speech_server_error::asrErrorCode2speechResult(int errorCode) {
    if (asrErrorCodeMap.count(errorCode) > 0) {
        return asrErrorCodeMap.at(errorCode);
    }

    return {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::UnsupportedScript};
}

baidu_speech_server_error::EngineErrorCode baidu_speech_server_error::realtimeAsrErrorCode2speechResult(int errorCode) {
    if (realtimeAsrErrorCodeMap.count(errorCode) > 0) {
        return realtimeAsrErrorCodeMap.at(errorCode);
    }

    return {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::UnsupportedScript};
}

baidu_speech_server_error::EngineErrorCode baidu_speech_server_error::ttsErrorCode2speechResult(int errorCode) {
    if (ttsErrorCodeMap.count(errorCode) > 0) {
        return ttsErrorCodeMap.at(errorCode);
    }

    return {ai_engine::EngineErrorCategory::OutputError, ai_engine::SpeechEngineErrorCode::UnsupportedScript};
}

const bool baidu_speech_server_error::isErrorRecoverable(int errorCode) {
    if (errorCode == -3003 || errorCode == -3005 || errorCode == -3013) {
        return true;
    }
    return false;
}
