/*******************************************************************************
 * Copyright (c) 2023, Jan Koester jan.koester@gmx.net
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#include <sstream>

#include "conf.h"

blogi::Config::Config(const std::string &path) : confplus::Config(path){
    for(size_t i =0; i<getElements(getKey("/BLOGI/PLUGINDIR")); ++i){
       _PlgDir.push_back(getValue(getKey("/BLOGI/PLUGINDIR"),i));
    }

    _DBDriver=getValue(getKey("/BLOGI/DATABASE/DRIVER"),0);
    _DBConnection=getValue(getKey("/BLOGI/DATABASE/CONNECTION"),0);
    _AuthUrl=getValue(getKey("/BLOGI/AUTHDB/URL"),0);
    _ClientName=getValue(getKey("/BLOGI/AUTHDB/CLIENTNAME"),0);
    _ClientSecret=getValue(getKey("/BLOGI/AUTHDB/CLIENTSECRET"),0);

    // Parse multi-domain AUTHDB sources (parallel arrays)
    try {
        auto *urlKey = getKey("/BLOGI/AUTHDB/URL");
        auto *nameKey = getKey("/BLOGI/AUTHDB/CLIENTNAME");
        auto *secretKey = getKey("/BLOGI/AUTHDB/CLIENTSECRET");
        size_t count = getElements(urlKey);
        for (size_t i = 0; i < count; ++i) {
            AuthSource src;
            src.url = getValue(urlKey, i);
            src.clientName = getValue(nameKey, i);
            src.clientSecret = getValue(secretKey, i);
            try {
                auto *domKey = getKey("/BLOGI/AUTHDB/DOMAIN");
                src.domain = getValue(domKey, i);
            } catch (...) {
                src.domain = "";
            }
            _AuthSources.push_back(std::move(src));
        }
    } catch (...) {
        // If multi-domain parsing fails, create a single source from legacy fields
        if (!_AuthUrl.empty()) {
            AuthSource src;
            src.url = _AuthUrl;
            src.clientName = _ClientName;
            src.clientSecret = _ClientSecret;
            src.domain = "";
            _AuthSources.push_back(std::move(src));
        }
    }
    _HttpBind=getValue(getKey("/BLOGI/HTTP/BIND"),0);
    try {
        _HttpPort = getIntValue(getKey("/BLOGI/HTTP/PORT"), 0);
    } catch (...) {
        _HttpPort = -1;
    }
    try {
        _MaxCon = getIntValue(getKey("/BLOGI/HTTP/MAXCON"), 0);
    } catch (...) {
        _MaxCon = -1;
    }
    _HttpUrl=getValue(getKey("/BLOGI/HTTP/URL"),0);
    _HttpPrefix=getValue(getKey("/BLOGI/HTTP/PREFIX"),0);
    if(_HttpPrefix == "/")
        _HttpPrefix = "";
    _Template=getValue(getKey("/BLOGI/TEMPLATE"),0);
    _StartPage=getValue(getKey("/BLOGI/STARTPAGE"),0);

    try{
        _SSLCertpath=getValue(getKey("/BLOGI/SSL/CERT"),0);
        _SSLKeypath=getValue(getKey("/BLOGI/SSL/KEY"),0);
    }catch(...){
    }
    try{
        _SSLPassword=getValue(getKey("/BLOGI/SSL/PASSWORD"),0);
    }catch(...){
    }
    _Domain=getValue(getKey("/BLOGI/DOMAIN/NAME"),0);

    try{
        _CookieDomain=getValue(getKey("/BLOGI/COOKIE/DOMAIN"),0);
    }catch(...){
        _CookieDomain=getValue(getKey("/BLOGI/DOMAIN/NAME"),0);
    }

    try{
        _TmpDir=getValue(getKey("/BLOGI/TMPDIR"),0);
    }catch(...){
        _TmpDir="/tmp/blogi";
    }

    try{
        _MediaDBUrl=getValue(getKey("/BLOGI/MEDIADB/URL"),0);
    }catch(...){
        _MediaDBUrl="https://127.0.0.1:8442";
    }
}

blogi::Config::~Config(){

}

const std::string blogi::Config::buildurl(const std::string &url) const{
    std::stringstream str;
    if(getprefix().empty() || getprefix() == "/")
        str << '/' << url;
    else
        str << getprefix() << '/' << url;
    return str.str();
}

const std::string &blogi::Config::getplgdir(size_t el) const {
    return _PlgDir[el];
}

size_t blogi::Config::getplgdirs() const {
    return _PlgDir.size();
}

const std::string & blogi::Config::getdbdriver() const {
    return _DBDriver;
}

const std::string & blogi::Config::getdbopts() const {
    return _DBConnection;
}

const std::string & blogi::Config::getAuthUrl() const {
    return _AuthUrl;
}

const std::string &blogi::Config::getClientName() const {
    return _ClientName;
}

const std::string & blogi::Config::getClientSecret() const {
    return _ClientSecret;
}

const std::string & blogi::Config::gethttpaddr() const {
    return _HttpBind;
}

int blogi::Config::gethttpport() const {
    return _HttpPort;
}

int blogi::Config::gethttpmaxcon() const {
    return _MaxCon;
}

const std::string & blogi::Config::getsiteurl() const {
    return _HttpUrl;
}

const std::string & blogi::Config::getprefix() const {
    return _HttpPrefix;
}


const std::string & blogi::Config::gettemplate() const {
    return _Template;
}

const std::string & blogi::Config::getstartpage() const {
    return _StartPage;
}

const std::string & blogi::Config::getsslcertpath() const {
    return _SSLCertpath;
}

const std::string & blogi::Config::getsslkeypath() const{
    return _SSLKeypath;
}

const std::string & blogi::Config::getsslpassword() const{
    return _SSLPassword;
}

const std::string & blogi::Config::getDomain() const{
    return _Domain;
}
const std::string & blogi::Config::getTmpDir() const{
    return _TmpDir;
}

const std::string & blogi::Config::getMediaDBUrl() const{
    return _MediaDBUrl;
}

size_t blogi::Config::getAuthSourceCount() const {
    return _AuthSources.size();
}

const blogi::AuthSource &blogi::Config::getAuthSource(size_t idx) const {
    return _AuthSources.at(idx);
}

const blogi::AuthSource *blogi::Config::findAuthSource(const std::string &domain) const {
    // If only one source and no domain specified, return it
    if (_AuthSources.size() == 1 && domain.empty()) {
        return &_AuthSources[0];
    }
    // Search by domain name (case-insensitive)
    for (const auto &src : _AuthSources) {
        std::string srcDomain = src.domain;
        std::string searchDomain = domain;
        // Simple lowercase compare
        for (auto &c : srcDomain) c = std::tolower(c);
        for (auto &c : searchDomain) c = std::tolower(c);
        if (srcDomain == searchDomain) return &src;
    }
    // Fallback: if no domain match and only one source, use it
    if (_AuthSources.size() == 1) {
        return &_AuthSources[0];
    }
    return nullptr;
}
