/*
 * Copyright (c) 2017, The Linux Foundation. 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * 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 <thread>
#include "CommandsTcpServer.h"
#include "TcpNetworkInterface.h"
#include "FileReader.h"
#include "Host.h"

using namespace std;

// *************************************************************************************************

CommandsTcpServer::CommandsTcpServer(unsigned int commandsTcpPort, Host& host)
    :m_port(commandsTcpPort),m_pSocket(new TcpNetworkInterfaces::NetworkInterface()), m_host(host), m_running(true)
{
}

// *************************************************************************************************

void CommandsTcpServer::Start()
{
    //LOG_INFO << "Starting commands TCP server on port " << m_port << endl;
    m_pSocket->Bind(m_port);
    m_pSocket->Listen();

    //Infinite loop that waits for clients to connect to the commands TCP server - there's no reason to stop this loop,
    //should run forever unless there is a problem
    while (m_running)
    {
        try
        {
            //thread serverThread = thread(&ServerThread, m_pServer->accept());
            thread serverThread(&CommandsTcpServer::ServerThread, this, m_pSocket->Accept()); //open a new thread for each client
            serverThread.detach();
        }
        catch (exception e)
        {
            LOG_ERROR << "Couldn't make a new connection or starting a new thread in Commands TCP server for a new client " << e.what() << endl;
        }
    }
}

void CommandsTcpServer::Stop()
{
    LOG_INFO << "Stopping the commands TCP server" << endl;
    m_pSocket->Close(); //type 2 -> Acts like the close(), shutting down both input and output
    m_pSocket.reset();
    m_running = false;
}



// *************************************************************************************************
//A thread function to handle each client that connects to the server
void CommandsTcpServer::ServerThread(TcpNetworkInterfaces::NetworkInterface client)
{
    unique_ptr<CommandsHandler> pCommandsHandler(new CommandsHandler(stTcp, m_host));
    ConnectionStatus keepConnectionAliveFromCommand = KEEP_CONNECTION_ALIVE; //A flag for the content of the command - says if the client wants to close connection
    ConnectionStatus keepConnectionAliveFromReply = KEEP_CONNECTION_ALIVE; //A flag for the reply status, for problems in sending reply etc..
    // notify that new clinet is connected to the host (send list of connected users before adding the new one, and a notification of the new one)
    Host::GetHost().PushEvent(ClientConnectedEvent(Host::GetHost().GetHostInfo().GetConnectedUsers(), client.GetPeerName()));
    m_host.GetHostInfo().AddNewConnectedUser(client.GetPeerName()); // add the user's to the host's connected users

    do
    {
        string concatenatedMessages;

        try
        {
            const char* message = client.Receive();
            if (NULL == message)
            {
                keepConnectionAliveFromReply = CLOSE_CONNECTION;
                break;
            }

            concatenatedMessages = message;
            vector<string> splitMessages = Utils::Split(concatenatedMessages, '\r');

            for (auto& message : splitMessages)
            {
                ResponseMessage referencedResponse;
                if (message.empty())
                { //message back from the client is "", means the connection is closed
                    break;
                }
                //Try to execute the command from the client, get back from function if to keep the connection with the client alive or not
                keepConnectionAliveFromCommand = pCommandsHandler->ExecuteCommand(message, referencedResponse);

                if (referencedResponse.type == REPLY_TYPE_WAIT_BINARY) {
                    uint8_t* binaryInput = (uint8_t*)client.BinaryReceive(referencedResponse.inputBufSize);
                    keepConnectionAliveFromCommand = pCommandsHandler->ExecuteBinaryCommand(binaryInput, referencedResponse);
                }

                //Reply back to the client an answer for his command. If it wasn't successful - close the connection
                keepConnectionAliveFromReply = CommandsTcpServer::Reply(client, referencedResponse);
            }
            //LOG_VERBOSE << "Message from Client to commands TCP server: " << message << endl;
        }
        catch (exception e)
        {
            LOG_ERROR << "Couldn't get the message from the client" << e.what() << endl;
            break;
        }

    } while (keepConnectionAliveFromCommand != CLOSE_CONNECTION && keepConnectionAliveFromReply != CLOSE_CONNECTION);

    //client.shutdown(0); //TODO - check how to do it correctly (without exception)
    //client.shutdown(1); //TODO - check how to do it correctly (without exception)
    //client.close(); //TODO - check how to do it correctly (without exception)
    LOG_INFO << "Closed connection with the client: " << client.GetPeerName() << endl;
    m_host.GetHostInfo().RemoveConnectedUser(client.GetPeerName());
    //notify that new client is disconnected from the host
    Host::GetHost().PushEvent(ClientDisconnectedEvent(Host::GetHost().GetHostInfo().GetConnectedUsers(), client.GetPeerName()));

}

// *************************************************************************************************

ConnectionStatus CommandsTcpServer::Reply(TcpNetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage)
{
    LOG_VERBOSE << "Reply is: " << responseMessage.message << endl;

    switch (responseMessage.type)
    {
    case REPLY_TYPE_BUFFER:
        return ReplyBuffer(client, responseMessage);
    case REPLY_TYPE_FILE:
        return ReplyFile(client, responseMessage);
    case REPLY_TYPE_BINARY:
        return ReplyBinary(client, responseMessage);
    default:
        LOG_ERROR << "Unknown reply type" << endl;
        return CLOSE_CONNECTION;
    }
}


// *************************************************************************************************

ConnectionStatus CommandsTcpServer::ReplyBuffer(TcpNetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage)
{
    LOG_VERBOSE << "Replying from a buffer (" << responseMessage.length << "B) Content: " << responseMessage.message << endl;

    if (0 == responseMessage.length)
    {
        LOG_ERROR << "No reply generated by a command handler - connection will be closed" << endl;
        return CLOSE_CONNECTION;
    }

    //TODO - maybe the sending format is ending with "\r\n"
    if (!client.SendString(responseMessage.message + "\r"))
    {
        LOG_ERROR << "Couldn't send the message to the client, closing connection" << endl;
        return CLOSE_CONNECTION;
    }

    return KEEP_CONNECTION_ALIVE;
}


//TODO - reply file had been copied from old "wilserver" almost without touching it.
//It has to be checked and also modified to fit the new "host_server_11ad"
//The same applies to "FileReader.h" and "FileReader.cpp"
ConnectionStatus CommandsTcpServer::ReplyFile(TcpNetworkInterfaces::NetworkInterface& client, ResponseMessage& fileName)
{
    FileReader fileReader(fileName.message.c_str());
    size_t fileSize = fileReader.GetFileSize();
    LOG_VERBOSE << "Replying from a file: " << fileName.message
              << " Size: " << fileSize << " B" << std::endl;

    if (0 == fileSize)
    {
        LOG_ERROR << "No file content is available for reply" << std::endl;
        return CLOSE_CONNECTION;
    }

    static const size_t SEND_BUFFER_LEN = 1024 * 1024;
    std::unique_ptr<char[]> spSendBuffer(new char[SEND_BUFFER_LEN]);
    if (!spSendBuffer)
    {
        LOG_ERROR << "Cannot allocate send buffer of " << SEND_BUFFER_LEN << " B";
        return CLOSE_CONNECTION;
    }

    size_t chunkSize = 0;
    do
    {
        LOG_VERBOSE << "Requesting for a file chunk of " << SEND_BUFFER_LEN << " B"  << std::endl;

        chunkSize = fileReader.ReadChunk(spSendBuffer.get(), SEND_BUFFER_LEN);
        if (chunkSize > 0)
        {
            LOG_ASSERT(chunkSize <= SEND_BUFFER_LEN);
            if (!client.SendBuffer(spSendBuffer.get(), chunkSize))
            {
                LOG_ERROR << "Error occurred while replying file content - transport error" << std::endl;
                return CLOSE_CONNECTION;
            }
        }

        // Error/Completion may occur with non-zero chunk as well
        if (fileReader.IsError())
        {
            LOG_ERROR << "Cannot send reply - file read error" << std::endl;
            return CLOSE_CONNECTION;
        }

        if (fileReader.IsCompleted())
        {
            LOG_VERBOSE << "File Content successfully delivered" << std::endl;
            return KEEP_CONNECTION_ALIVE;
        }

        LOG_VERBOSE << "File Chunk Delivered: " << chunkSize << "B" << std::endl;
    }
    while (chunkSize > 0);

    return KEEP_CONNECTION_ALIVE;
}

ConnectionStatus CommandsTcpServer::ReplyBinary(TcpNetworkInterfaces::NetworkInterface &client, ResponseMessage &responseMessage)
{
    if (0 == responseMessage.length)
    {
        LOG_ERROR << "No reply generated by a command handler - connection will be closed" << endl;
        return CLOSE_CONNECTION;
    }

    if (!client.SendBuffer((const char*)responseMessage.binaryMessage, responseMessage.length))
    {
        LOG_ERROR << "Couldn't send the message to the client, closing connection" << endl;
        return CLOSE_CONNECTION;
    }

    return KEEP_CONNECTION_ALIVE;
}