#include <iostream>
#include <memory>
#include <string>

#include <Poco/Logger.h>
#include "Poco/FileChannel.h"
#include <Poco/FormattingChannel.h>
#include <Poco/PatternFormatter.h>
#include "query_analyzer.h"
#include "server_config.h"

using Poco::FormattingChannel;
using Poco::FileChannel;
using Poco::PatternFormatter;
using Poco::AutoPtr;
using Poco::Util::ServerApplication;


void init_config(AbstractConfiguration &config){
    // get original launching path before daemonizing
    std::string cwd(getenv("POCO_CWD"));

    // init logging
    ServerConfig* confIns = ServerConfig::getInstance();
    confIns->LoadConfig(config);

    AutoPtr<Poco::Channel> pFileChannel(new FileChannel);
    std::string logPath = config.getString("log_path");
    if (logPath[0] != '/')
        logPath = cwd + "/" + logPath;
    pFileChannel->setProperty("path", logPath);
    pFileChannel->setProperty("rotation", "00:00");
    pFileChannel->setProperty("archive", "timestamp");
    pFileChannel->setProperty("times", "local");
    pFileChannel->setProperty("purgeAge", "30 days");
    AutoPtr<PatternFormatter> pPF(new PatternFormatter);
    pPF->setProperty("times", "local");
    pPF->setProperty("pattern", "[%Y-%m-%d %H:%M:%S] %P-%I %p: %t");
    AutoPtr<FormattingChannel> pFC(new FormattingChannel(pPF, pFileChannel));
    Poco::Logger::root().setChannel(pFC);
    Poco::Logger& logger = Poco::Logger::get("StrategyServer"); // inherits root channel
}

void RunServer(AbstractConfiguration &config) {

	std::string stHost = config.getString("host");
    std::string stPort = config.getString("port");
	std::string server_address(stHost + ":" + stPort);
	QueryAnalyzerImpl service;

	grpc::EnableDefaultHealthCheckService(true);
	grpc::reflection::InitProtoReflectionServerBuilderPlugin();
	ServerBuilder builder;
	// Listen on the given address without any authentication mechanism.
	builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
	// Register "service" as the instance through which we'll communicate with
	// clients. In this case it corresponds to an *synchronous* service.
	builder.RegisterService(&service);
	// Finally assemble the server.
	std::unique_ptr<Server> server(builder.BuildAndStart());
	std::cout << "Server listening on " << server_address << std::endl;

	// Wait for the server to shutdown. Note that some other thread must be
	// responsible for shutting down the server for this call to ever return.
	server->Wait();
}


int main(int argc,char **argv){

    AbstractConfiguration &config(Application::instance().config());

	init_config(config);
	RunServer(config);

	return 1;
}
