#include "TCPSession2.h"
#include "Exception.h"
#include "Log.h"

namespace core {

   TCPSession2::TCPSession2(EPoll &ePoll, std::string text) : TCPSocket(ePoll, text) {}

   TCPSession2::~TCPSession2() {}

   void TCPSession2::output(std::stringstream &data) {
      data << "|" << ipAddress.getClientAddressAndPort();
   }

   void TCPSession2::protocol(coreutils::ZString &data) {}

   void TCPSession2::onRegistered() {
      onConnected();
      send();
      if(term)
        TCPSocket::shutdown("termination requested");
   }

   void TCPSession2::onConnected() {}

   void TCPSession2::onDataReceived(coreutils::ZString &data) {
      if(data.getLength() > 0) {
	 lineBuffer = (char *)realloc(lineBuffer, lineBufferSize + data.getLength());
	 memcpy(lineBuffer + lineBufferSize, data.getData(), data.getLength());
	 lineBufferSize += data.getLength();
	 while(lineBufferSize > 0) {
	    if(blockSize == 0) {
	       lineLength = strcspn(lineBuffer, "\r\n");
	       if(lineLength == lineBufferSize)
		 break;
               coreutils::ZString zLine(lineBuffer, lineLength);
	       onLineReceived(zLine);
	       if(lineBuffer[lineLength] == '\r')
		 ++lineLength;
	       if(lineBuffer[lineLength] == '\n')
		 ++lineLength;
	       lineBufferSize -= lineLength;
	       if(lineBufferSize > 0)
		 memmove(lineBuffer, lineBuffer + lineLength, lineBufferSize);
	       lineBuffer = (char *)realloc(lineBuffer, lineBufferSize);
            } else if(lineBufferSize >= blockLength) {
	       coreutils::ZString zBlock(lineBuffer, blockLength);
	       onBlockReceived(zBlock);
	       lineBufferSize -= blockLength;
	       if(lineBufferSize > 0)
		 memmove(lineBuffer, lineBuffer + blockLength, lineBufferSize);
	       lineBuffer = (char *)realloc(lineBuffer, lineBufferSize);
	    }
	 }
      }
   }

   void TCPSession2::setBlockSize(int blockSize) {
      this->blockSize = blockSize;
   }

   void TCPSession2::onLineReceived(coreutils::ZString &line) {
      protocol(line);
      send();
      if(term)
        TCPSocket::shutdown("termination requested");
   }

   void TCPSession2::onBlockReceived(coreutils::ZString &block) {
      coreutils::Log(coreutils::LOG_DEBUG_3) << "[" << block.getLength() << "]";
      if(term)
        TCPSocket::shutdown("termination requested");
   }

   void TCPSession2::send() {
      if(out.tellp() > 0)
	     TCPSocket::write(out.str());
      out.str("");
   }

   void TCPSession2::terminate() {
      term = true;
   }

}
