/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 <log4cxx/db/dbappender.h>
#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/patternlayout.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/pattern/loggerpatternconverter.h>
#include <log4cxx/pattern/classnamepatternconverter.h>
#include <log4cxx/pattern/datepatternconverter.h>
#include <log4cxx/pattern/filelocationpatternconverter.h>
#include <log4cxx/pattern/fulllocationpatternconverter.h>
#include <log4cxx/pattern/shortfilelocationpatternconverter.h>
#include <log4cxx/pattern/linelocationpatternconverter.h>
#include <log4cxx/pattern/messagepatternconverter.h>
#include <log4cxx/pattern/methodlocationpatternconverter.h>
#include <log4cxx/pattern/levelpatternconverter.h>
#include <log4cxx/pattern/threadpatternconverter.h>
#include <log4cxx/pattern/threadusernamepatternconverter.h>
#include <log4cxx/pattern/ndcpatternconverter.h>
#include <log4cxx/private/appenderskeleton_priv.h>
#include <apr_dbd.h>
#include <assert.h>

using namespace LOG4CXX_NS;
using namespace LOG4CXX_NS::helpers;
using namespace LOG4CXX_NS::db;
using namespace LOG4CXX_NS::spi;
using namespace LOG4CXX_NS::pattern;

IMPLEMENT_LOG4CXX_OBJECT(DBAppender)

#define _priv static_cast<DBAppenderPriv*>(m_priv.get())

struct DBAppender::DBAppenderPriv : public AppenderSkeleton::AppenderSkeletonPrivate
{
    DBAppenderPriv() :
        AppenderSkeletonPrivate()
	{
		static bool initialized = false;
		if (!initialized)
		{
			initialized = true;
			apr_status_t stat = apr_dbd_init(m_pool.getAPRPool());
			assert(stat == APR_SUCCESS);
		}
	}

    const apr_dbd_driver_t* m_driver = nullptr;
    apr_dbd_t* m_databaseHandle = nullptr;
    apr_dbd_prepared_t* preparedStmt = nullptr;
    std::vector<LogString> mappedName;
    std::string driverName;
    std::string driverParams;
    std::string databaseName;
    std::string sqlStatement;
    Pool m_pool;
    std::vector<pattern::LoggingEventPatternConverterPtr> converters;
};

#define RULES_PUT(spec, cls) \
    specs.insert(PatternMap::value_type(LogString(LOG4CXX_STR(spec)), cls ::newInstance))

static PatternMap getFormatSpecifiers()
{
    PatternMap specs;
    if (specs.empty())
    {
        RULES_PUT("logger", LoggerPatternConverter);
        RULES_PUT("class", ClassNamePatternConverter);
        RULES_PUT("time", DatePatternConverter);
        RULES_PUT("shortfilename", ShortFileLocationPatternConverter);
        RULES_PUT("fullfilename", FileLocationPatternConverter);
        RULES_PUT("location", FullLocationPatternConverter);
        RULES_PUT("line", LineLocationPatternConverter);
        RULES_PUT("message", MessagePatternConverter);
        RULES_PUT("method", MethodLocationPatternConverter);
        RULES_PUT("level", LevelPatternConverter);
        RULES_PUT("thread", ThreadPatternConverter);
        RULES_PUT("threadname", ThreadUsernamePatternConverter);
        RULES_PUT("ndc", NDCPatternConverter);
    }
    return specs;
}

DBAppender::DBAppender()
    : AppenderSkeleton (std::make_unique<DBAppenderPriv>())
{
}

DBAppender::~DBAppender()
{
    close();
}

void DBAppender::close(){
    if(_priv->m_driver && _priv->m_databaseHandle){
        apr_dbd_close(_priv->m_driver, _priv->m_databaseHandle);
    }
    _priv->m_driver = nullptr;
    _priv->m_databaseHandle = nullptr;
}

void DBAppender::setOption(const LogString& option, const LogString& value){
    if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("COLUMNMAPPING"), LOG4CXX_STR("columnmapping")))
    {
        _priv->mappedName.push_back(value);
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DRIVERNAME"), LOG4CXX_STR("drivername")))
    {
        Transcoder::encodeUTF8(value, _priv->driverName);
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DRIVERPARAMS"), LOG4CXX_STR("driverparams")))
    {
        Transcoder::encodeUTF8(value, _priv->driverParams);
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("DATABASENAME"), LOG4CXX_STR("databasename")))
    {
        Transcoder::encodeUTF8(value, _priv->databaseName);
    }
    else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SQL"), LOG4CXX_STR("sql")))
    {
        Transcoder::encodeUTF8(value, _priv->sqlStatement);
    }
    else
    {
        AppenderSkeleton::setOption(option, value);
    }
}

void DBAppender::activateOptions(helpers::Pool& p){
    apr_status_t stat = apr_dbd_get_driver(_priv->m_pool.getAPRPool(),
                                           _priv->driverName.c_str(),
#if 15 < LOG4CXX_ABI_VERSION
                                           &_priv->m_driver);
#else
                                           const_cast<const apr_dbd_driver_t**>(&_priv->m_driver));
#endif

    if(stat != APR_SUCCESS){
        LogString errMsg = LOG4CXX_STR("Unable to get driver named ");
        LOG4CXX_DECODE_CHAR(driverName, _priv->driverName);
        errMsg.append(driverName);
        LogLog::error(errMsg);
        _priv->errorHandler->error(errMsg);
        return;
    }

    stat = apr_dbd_open(_priv->m_driver,
                        _priv->m_pool.getAPRPool(),
                        _priv->driverParams.c_str(),
                        &_priv->m_databaseHandle);
    if(stat != APR_SUCCESS){
        LogLog::error(LOG4CXX_STR("Unable to open database"));
        _priv->errorHandler->error(LOG4CXX_STR("Unable to open database"));
        return;
    }

    if(!_priv->databaseName.empty()){
        apr_dbd_set_dbname(_priv->m_driver,
                           _priv->m_pool.getAPRPool(),
                           _priv->m_databaseHandle,
                           _priv->databaseName.c_str());
    }

    stat = apr_dbd_prepare(_priv->m_driver,
                           _priv->m_pool.getAPRPool(),
                           _priv->m_databaseHandle,
                           _priv->sqlStatement.c_str(),
                           "log_insert",
                           &_priv->preparedStmt);
    if(stat != APR_SUCCESS){
        LogString error = LOG4CXX_STR("Unable to prepare statement: ");
        std::string dbdErr(apr_dbd_error(_priv->m_driver, _priv->m_databaseHandle, stat));
        LOG4CXX_DECODE_CHAR(dbdErrLS, dbdErr);
        error.append(dbdErrLS);
        LogLog::error(error);
        _priv->errorHandler->error(error);
        return;
    }

    auto specs = getFormatSpecifiers();
    for (auto& name : _priv->mappedName)
    {
        auto pItem = specs.find(StringHelper::toLowerCase(name));
        if (specs.end() == pItem)
            LogLog::error(name + LOG4CXX_STR(" is not a supported ColumnMapping value"));
        else
        {
            std::vector<LogString> options;
            if (LOG4CXX_STR("time") == pItem->first)
                options.push_back(LOG4CXX_STR("yyyy-MM-ddTHH:mm:ss.SSS"));
            pattern::LoggingEventPatternConverterPtr converter = LOG4CXX_NS::cast<LoggingEventPatternConverter>((pItem->second)(options));
            _priv->converters.push_back(converter);
        }
    }
}

void DBAppender::append(const spi::LoggingEventPtr& event, helpers::Pool& p){
	std::vector<std::string> ls_args;
    std::vector<const char*> args;
    int stat;
    int num_rows;

    if(_priv->m_driver == nullptr ||
            _priv->m_databaseHandle == nullptr ||
            _priv->preparedStmt == nullptr){
        _priv->errorHandler->error(LOG4CXX_STR("DBAppender not initialized properly: logging not available"));
        return;
    }

    for(auto& converter : _priv->converters){
        LogString str_data;
        converter->format(event, str_data, p);
		LOG4CXX_ENCODE_CHAR(new_str_data, str_data);
		ls_args.push_back(new_str_data);
    }

	for(std::string& str : ls_args){
        args.push_back(str.data());
    }
    args.push_back(nullptr);

    stat = apr_dbd_pquery(_priv->m_driver,
                          _priv->m_pool.getAPRPool(),
                          _priv->m_databaseHandle,
                          &num_rows,
                          _priv->preparedStmt,
                          int(args.size()),
                          args.data());
    if(stat != APR_SUCCESS){
        LogString error = LOG4CXX_STR("Unable to insert: ");
		LOG4CXX_DECODE_CHAR(local_error, apr_dbd_error(_priv->m_driver, _priv->m_databaseHandle, stat));
		error.append(local_error);
        LogLog::error(error);
        _priv->errorHandler->error(error);
    }
}
