// CODYlib		-*- mode:c++ -*-
// Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
// License: Apache v2.0

// Cody
#include "internal.hh"
// C++
#include <tuple>
// C
#include <cerrno>
#include <cstdlib>
#include <cstring>

// Server code

namespace Cody {

// These do not need to be members
static Resolver *ConnectRequest (Server *, Resolver *,
				 std::vector<std::string> &words);
static int ModuleRepoRequest (Server *, Resolver *,
			      std::vector<std::string> &words);
static int ModuleExportRequest (Server *, Resolver *,
				std::vector<std::string> &words);
static int ModuleImportRequest (Server *, Resolver *,
				std::vector<std::string> &words);
static int ModuleCompiledRequest (Server *, Resolver *,
				  std::vector<std::string> &words);
static int IncludeTranslateRequest (Server *, Resolver *,
				     std::vector<std::string> &words);
static int InvokeSubProcessRequest (Server *, Resolver *,
				     std::vector<std::string> &words);

namespace {
using RequestFn = int (Server *, Resolver *, std::vector<std::string> &);
using RequestPair = std::tuple<char const *, RequestFn *>;
static RequestPair
  const requestTable[Detail::RC_HWM] =
  {
    // Same order as enum RequestCode
    RequestPair {u8"HELLO", nullptr},
    RequestPair {u8"MODULE-REPO", ModuleRepoRequest},
    RequestPair {u8"MODULE-EXPORT", ModuleExportRequest},
    RequestPair {u8"MODULE-IMPORT", ModuleImportRequest},
    RequestPair {u8"MODULE-COMPILED", ModuleCompiledRequest},
    RequestPair {u8"INCLUDE-TRANSLATE", IncludeTranslateRequest},
    RequestPair {u8"INVOKE", InvokeSubProcessRequest},
  };
}

Server::Server (Resolver *r)
  : resolver (r), direction (READING)
{
  PrepareToRead ();
}

Server::Server (Server &&src)
  : write (std::move (src.write)),
    read (std::move (src.read)),
    resolver (src.resolver),
    is_connected (src.is_connected),
    direction (src.direction)
{
  fd.from = src.fd.from;
  fd.to = src.fd.to;
}

Server::~Server ()
{
}

Server &Server::operator= (Server &&src)
{
  write = std::move (src.write);
  read = std::move (src.read);
  resolver = src.resolver;
  is_connected = src.is_connected;
  direction = src.direction;
  fd.from = src.fd.from;
  fd.to = src.fd.to;

  return *this;
}

void Server::DirectProcess (Detail::MessageBuffer &from,
			    Detail::MessageBuffer &to)
{
  read.PrepareToRead ();
  std::swap (read, from);
  ProcessRequests ();
  resolver->WaitUntilReady (this);
  write.PrepareToWrite ();
  std::swap (to, write);
}

void Server::ProcessRequests (void)
{
  std::vector<std::string> words;

  direction = PROCESSING;
  while (!read.IsAtEnd ())
    {
      int err = 0;
      unsigned ix = Detail::RC_HWM;
      if (!read.Lex (words))
	{
	  Assert (!words.empty ());
	  while (ix--)
	    {
	      if (words[0] != std::get<0> (requestTable[ix]))
		continue; // not this one

	      if (ix == Detail::RC_CONNECT)
		{
		  // CONNECT
		  if (IsConnected ())
		    err = -1;
		  else if (auto *r = ConnectRequest (this, resolver, words))
		    resolver = r;
		  else
		    err = -1;
		}
	      else
		{
		  if (!IsConnected ())
		    err = -1;
		  else if (int res = (std::get<1> (requestTable[ix])
				      (this, resolver, words)))
		    err = res;
		}
	      break;
	    }
	}

      if (err || ix >= Detail::RC_HWM)
	{
	  // Some kind of error
	  std::string msg;

	  if (err > 0)
	    msg = u8"error processing '";
	  else if (ix >= Detail::RC_HWM)
	    msg = u8"unrecognized '";
	  else if (IsConnected () && ix == Detail::RC_CONNECT)
	    msg = u8"already connected '";
	  else if (!IsConnected () && ix != Detail::RC_CONNECT)
	    msg = u8"not connected '";
	  else
	    msg = u8"malformed '";

	  read.LexedLine (msg);
	  msg.append (u8"'");
	  if (err > 0)
	    {
	      msg.append (u8" ");
	      msg.append (strerror (err));
	    }
	  resolver->ErrorResponse (this, std::move (msg));
	}
    }
}

// Return numeric value of STR as an unsigned.  Returns ~0u on error
// (so that value is not representable).
static unsigned ParseUnsigned (std::string &str)
{
  char *eptr;
  unsigned long val = strtoul (str.c_str (), &eptr, 10);
  if (*eptr || unsigned (val) != val)
    return ~0u;

  return unsigned (val);
}

Resolver *ConnectRequest (Server *s, Resolver *r,
			  std::vector<std::string> &words)
{
  if (words.size () < 3 || words.size () > 4)
    return nullptr;

  if (words.size () == 3)
    words.emplace_back (u8"");
  unsigned version = ParseUnsigned (words[1]);
  if (version == ~0u)
    return nullptr;

  return r->ConnectRequest (s, version, words[2], words[3]);
}

int ModuleRepoRequest (Server *s, Resolver *r,std::vector<std::string> &words)
{
  if (words.size () != 1)
    return -1;

  return r->ModuleRepoRequest (s);
}

int ModuleExportRequest (Server *s, Resolver *r, std::vector<std::string> &words)
{
  if (words.size () < 2 || words.size () > 3 || words[1].empty ())
    return -1;

  Flags flags = Flags::None;
  if (words.size () == 3)
    {
      unsigned val = ParseUnsigned (words[2]);
      if (val == ~0u)
	return -1;
      flags = Flags (val);
    }

  return r->ModuleExportRequest (s, flags, words[1]);
}

int ModuleImportRequest (Server *s, Resolver *r, std::vector<std::string> &words)
{
  if (words.size () < 2 || words.size () > 3 || words[1].empty ())
    return -1;

  Flags flags = Flags::None;
  if (words.size () == 3)
    {
      unsigned val = ParseUnsigned (words[2]);
      if (val == ~0u)
	return -1;
      flags = Flags (val);
    }

  return r->ModuleImportRequest (s, flags, words[1]);
}

int ModuleCompiledRequest (Server *s, Resolver *r,
			   std::vector<std::string> &words)
{
  if (words.size () < 2 || words.size () > 3 || words[1].empty ())
    return -1;

  Flags flags = Flags::None;
  if (words.size () == 3)
    {
      unsigned val = ParseUnsigned (words[2]);
      if (val == ~0u)
	return -1;
      flags = Flags (val);
    }

  return r->ModuleCompiledRequest (s, flags, words[1]);
}

int IncludeTranslateRequest (Server *s, Resolver *r,
			     std::vector<std::string> &words)
{
  if (words.size () < 2 || words.size () > 3 || words[1].empty ())
    return -1;

  Flags flags = Flags::None;
  if (words.size () == 3)
    {
      unsigned val = ParseUnsigned (words[2]);
      if (val == ~0u)
	return -1;
      flags = Flags (val);
    }

  return r->IncludeTranslateRequest (s, flags, words[1]);
}

int InvokeSubProcessRequest (Server *s, Resolver *r,
			     std::vector<std::string> &args)
{
  if (args.size () < 2 || args[1].empty ())
    return -1;

  return r->InvokeSubProcessRequest (s, args);
}

void Server::ErrorResponse (char const *error, size_t elen)
{
  write.BeginLine ();
  write.AppendWord (u8"ERROR");
  write.AppendWord (error, true, elen);
  write.EndLine ();
}

void Server::OKResponse ()
{
  write.BeginLine ();
  write.AppendWord (u8"OK");
  write.EndLine ();
}

void Server::ConnectResponse (char const *agent, size_t alen)
{
  is_connected = true;

  write.BeginLine ();
  write.AppendWord (u8"HELLO");
  write.AppendInteger (Version);
  write.AppendWord (agent, true, alen);
  write.EndLine ();
}

void Server::PathnameResponse (char const *cmi, size_t clen)
{
  write.BeginLine ();
  write.AppendWord (u8"PATHNAME");
  write.AppendWord (cmi, true, clen);
  write.EndLine ();
}

void Server::BoolResponse (bool truthiness)
{
  write.BeginLine ();
  write.AppendWord (u8"BOOL");
  write.AppendWord (truthiness ? u8"TRUE" : u8"FALSE");
  write.EndLine ();
}

}
