/*
 * Copyright (C) 2013-2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "Prekill.h"

// ============ 配置管理器实现 ============
PrekillConfigManager& PrekillConfigManager::getInstance()
{
    static PrekillConfigManager instance;
    return instance;
}

bool PrekillConfigManager::init()
{
    if (mInitialized) {
        return true;
    }

    // 1. 加载 XML 配置
    mXmlDoc                  = std::make_shared<tinyxml2::XMLDocument>();
    tinyxml2::XMLError error = mXmlDoc->LoadFile(PREKILL_CONFIG_PATH);
    if (error != tinyxml2::XMLError::XML_SUCCESS) {
        ALOGE("Load XML failed: %s, error: %d", PREKILL_CONFIG_PATH, error);
        return false;
    }

    // 2. 加载配置项定义
    if (!loadConfigDefs()) {
        ALOGE("Failed to load config definitions");
        return false;
    }

    // 3. 获取机型信息
    mRamSize     = getRamSize();
    mProjectName = getProjectName();

    // 4. 循环设置所有属性
    applyAllProperties();

    mInitialized = true;
    ALOGD("PrekillConfig init: ram=%s, project=%s", mRamSize.c_str(), mProjectName.c_str());
    return true;
}
int PrekillConfigManager::getValue(const std::string& configName, int defaultValue)
{
    return getXmlValue(configName, defaultValue);
}
bool PrekillConfigManager::loadConfigDefs()
{
    tinyxml2::XMLElement* pRoot = mXmlDoc->FirstChildElement("camera");
    if (!pRoot)
        return false;

    tinyxml2::XMLElement* pConfigDefs = pRoot->FirstChildElement("config_defs");
    if (!pConfigDefs)
        return false;

    tinyxml2::XMLElement* pItem = pConfigDefs->FirstChildElement("item");
    while (pItem) {
        ConfigItem item;

        const char* name       = pItem->Attribute("name");
        const char* property   = pItem->Attribute("property");
        const char* defaultStr = pItem->Attribute("default");

        if (name && property) {
            item.name         = name;
            item.property     = property;
            item.defaultValue = defaultStr ? std::atoi(defaultStr) : 0;
            mConfigItems.push_back(item);
            ALOGD("Config def: name=%s, property=%s, default=%d", item.name.c_str(), item.property.c_str(), item.defaultValue);
        }

        pItem = pItem->NextSiblingElement("item");
    }

    return !mConfigItems.empty();
}

void PrekillConfigManager::applyAllProperties()
{
    for (const auto& item : mConfigItems) {
        int value = getXmlValue(item.name, item.defaultValue);
        setProperty(item.property.c_str(), value);
        ALOGD("Set property: %s = %d", item.property.c_str(), value);
    }
}

int PrekillConfigManager::getXmlValue(const std::string& configName, int defaultValue)
{
    tinyxml2::XMLElement* pRoot = mXmlDoc->FirstChildElement("camera");
    if (!pRoot)
        return defaultValue;

    tinyxml2::XMLElement* pPrekill = pRoot->FirstChildElement("prekill");
    if (!pPrekill)
        return defaultValue;

    std::vector<std::string> path = {mRamSize, mProjectName, configName};
    tinyxml2::XMLElement* pConfig = findElement(pPrekill, path);

    if (!pConfig) {
        ALOGW("Config not found: %s for %s/%s", configName.c_str(), mRamSize.c_str(), mProjectName.c_str());
        return defaultValue;
    }

    const char* value = pConfig->GetText();
    return value ? std::atoi(value) : defaultValue;
}

tinyxml2::XMLElement* PrekillConfigManager::findElement(tinyxml2::XMLElement* root, const std::vector<std::string>& path)
{
    tinyxml2::XMLElement* current = root;
    for (const auto& name : path) {
        if (!current)
            return nullptr;
        current = current->FirstChildElement(name.c_str());
    }
    return current;
}

void PrekillConfigManager::setProperty(const char* key, int value)
{
    char buf[32];
    snprintf(buf, sizeof(buf), "%d", value);
    property_set(key, buf);
}

// ============ 函数实现 ============
bool prekillInitInternal()
{
    return PrekillConfigManager::getInstance().init();
}

int getConfigValue(const std::string& name, int defaultValue)
{
    return PrekillConfigManager::getInstance().getValue(name, defaultValue);
}

int getCameraPrekillSizeByProject()
{
    return getConfigValue("camera_prekill_size", 0);
}

int getThirdPrekillSizeByProject()
{
    return getConfigValue("third_prekill_size", 0);
}

int getAnonCompressThresholdByProject()
{
    return getConfigValue("anon_compress_threshold", 0);
}

std::string getProperty(const char* key, const char* defaultValue)
{
    char value[PROPERTY_VALUE_MAX];
    memset(value, 0, sizeof(value)); // 先清零
    property_get(key, value, defaultValue);
    ALOGD("getProperty: key=%s, value=[%s], default=%s", key, value, defaultValue);
    return std::string(value);
}

std::string getRamSize()
{
    return "ram" + getProperty("sys.vivo.project.ramsize", "8");
}

std::string getProjectName()
{
    return getProperty("ro.vivo.product.model", "default");
}