/*
 * Copyright (c) 1995, 1996 Gunther Schadow.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * This is a simple example of a HL7 server application using the
 * ANYmsg server feature of ProtoGen/HL7. It does nothing else than
 * acknowledging a message that has been received. However, you can
 * take this as a template for the development of much more
 * sophisticated HL7 servers.
 */

#include <unistd.h>
#include <strstream.h>
#include "hl7/ANYmsg.h"
#include "hl7/ACKmsg.h"
#include "xios.h"
#include "logfile.h"
#include "ParseTrace.h"
#include "hl7/parsetrace.h"

#ifdef DEBUG
# ifdef LOGLEVEL
#   undef LOGLEVEL
# endif
# define LOGLEVEL L_JUNK
#else
# ifndef LOGLEVEL
#   define LOGLEVEL L_MESG
# endif
#endif

/* The ANYmsg server facility allows you to build HL7 server
 * applications very easily. The ANYmsg server waits for a connection
 * to be made on a TCP port and reads the HL7 request message. After
 * the connection and the message has passed the access control check
 * the ANYmsg server calls a server function if one was registered for
 * the request message/event type. A server function takes a request
 * message as it's argument and returns a pointer to a result message.
 *
 * Here we define the ack_service function that builds an ACKmsg with
 * application accept (AA). The ERRseg is used to return parser
 * warnings if they occured. The request message and the ACK message
 * is logged to the standard output channel, depending on a quiet flag
 * being cleared.
 */

static bool quiet = FALSE;

HL7Message *ack_service(HL7Message &msg)
{
  xios xout(cout);
  if(!quiet)
    cout << hl7er << "Request:" << endl << msg << endl;

  ACKmsg  &ack = *new ACKmsg;
  
  // MSA segment
  ack.MesAck.Ack = AckCode::AppAcc;
  ack.MesAck.MesConTrolId = msg.MesHea.MesConTrolId;
  ack.MesAck.TextMes = "message accepted";
  
  // ERR segment might contain warnings even for an acceptable message
  ack.Error = parseErrorSegment;
  
  // MSH segment
  ack.MesHea.SenApp = "HL7TEST";
  ack.MesHea.RecApp = msg.MesHea.SenApp;
  ack.MesHea.RecFac = msg.MesHea.SenFac;
  stamp(ack.MesHea.DateTimeOfMes);

  strstream s;
  s.form("RES%05u",(u_int)getpid());
  s << '\0';
  ack.MesHea.MesConTrolId = s.str();
  s.freeze(0);

  ack.MesHea.ProId = ProIdCode::Pro;
#ifdef HL7V21
  ack.MesHea.VerId = 2.1;
#else
  ack.MesHea.VerId = VerIdCode::_2_2val;
#endif
  
  ack.commit();

  if(!quiet)
    cout << "Result:" << endl << ack << endl;

  return &ack;
}

/* The main function is very simple and is made up of merely argument
 * processing, and initialization of the ANYmsg server. If the logger
 * is not initialized it writes to a default file.
 */

int
main(int argc, char *argv[])
{
  const char *service;

  // read arguments
  if(argc == 3 && strcmp(argv[1],"-q") == 0)
    {
      quiet = TRUE;
      service = argv[2];
    }
  else if(argc == 2)
    service = argv[1];
  else
    {
      cerr << "usage: " << argv[0] << " [-q] service" << endl;
      exit(1);
    }

  // initialize logger and log a message
  log_init(argv[0], "/tmp/server.log", (char*)service);
  log_level(LOGLEVEL);
  LOGINFO("HL7TEST server startup");

  // initialize the ANYmsg server
  ANYmsg any;

  // register our ACK-service for all message/event types
  for(UniMesIdCode::Value i = UniMesIdCode::first; i <= UniMesIdCode::last;
      i = (UniMesIdCode::Value)(i + 1))
    any.register_service(i, ack_service);
  
  // and begin serving
  any.serve(service, "HL7TEST");

  // this point is not normally reached, since the server runs until
  // it is terminated by a signal.

  return 0;
}
