#! /bin/sh

prefix=/usr
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib

PATH=$PATH:$prefix/bin
export PATH

usage()
{
    cat 1>&2 <<EOF
Usage: $0 [OPTION]

Known values for OPTION are:

  --libs            print library linking information
  --cxxflags        print pre-processor and compiler flags
  --config[=app]    print default configuration-file
  --makefile[=app]  print simple makefile for a ecpp-project
  --properties=app  print a properties file
  --project=app     create a simple ecpp-project-directory
  -p=app            shortcut for --project=app
  --autoproject=app create a autotools based tntnet project
  --help            display this help and exit
  --version         output version information
EOF

    exit $1
}

template()
{
    cat <<EOF
# This is the main configuration file for tntnet.
#
# You can find documentation about the parameters in the man page tntnet.conf(7)
#

EOF
  if test -z "$1"
  then
    cat <<EOF
# map /webapp/comp.* or /webapp/comp to comp@webapp
MapUrl      ^/(.+)/([^.]+)(\..+)?  \$2@\$1
# map /comp.* or /comp to comp@comp
MapUrl      ^/([^.]+)(\..+)?       \$1@\$1
EOF
  else
    cat <<EOF
# map / to $1@$1
MapUrl      ^/$   $1@$1
# map /comp.* or /comp to comp@$1
MapUrl      ^/([^.]+)(\..+)?   \$1@$1
EOF
  fi

  cat <<EOF

# listen to a port (empty string means any local interface)
Listen              "" 8000

# to enable ssl, we need a Certificate and another listen-command
#SslListen          "" 8443    tntnet.pem

# this propertyfile defines, what and where to log
PropertyFile        tntnet.properties

# set limit to prevent DoS-attacks (default 0=no limit)
#MaxRequestSize     65536
#MaxRequestTime     600  # request timeout for the watchdog, when tntnet runs as a daemon
#User               tntnet
#Group              tntnet
#Dir                /
#Chroot             /var/safedir
#PidFile            /var/run/tntnet.pid
#Daemon             0
#MinThreads         5
#MaxThreads         100
#ThreadStartDelay   10  # in ms
#QueueSize          1000
#CompPath           path
#BufferSize         16384
#SocketReadTimeout  10
#SocketWriteTimeout 10000
#KeepAliveTimeout   15000
#KeepAliveMax       1000
#SessionTimeout     300
#ListenBacklog      64
#ListenRetry        5
#EnableCompression  no
#MimeDb             /etc/mime.types
#MinCompressSize    1024  # in bytes
#MaxUrlMapCache     8192
#DefaultContentType "text/html; charset=UTF-8"
#AccessLog          /var/log/tntnet/access.log
#ErrorLog          /var/log/tntnet/error.log
#MaxBackgroundTasks 5
EOF
}

properties()
{
  cat <<EOF
# sample logging-properties for tntnet application $1
#
# print logging-messages with:
#   log_fatal("some fatal message");
#   log_error("some error message");
#   log_warn("some warn message");
#   log_info("some info message");
#   log_debug("some debug message");
#
rootLogger=INFO

# define logger-categories
logger.tntnet=INFO
logger.component.$1=INFO

# uncomment if you want to log to a file
#file=tntnet.log
#maxfilesize=1MB
#maxbackupindex=2
#host=localhost:1234  # send log-messages with udp
#disabled=1  # disable logging
#logprocess=1  # log through separate process
#logprocesuser=someuser  # change to user in log process
#logprocesgroup=somegroup  # change to group in log process
EOF
}

makefile()
{
  if test ! -z "$1"
  then
    cat <<EOF
all: $1.so

test: all
	\${TNTNET} tntnet.conf

$1.so: $1.o
	\${CXX} -o \$@ \${LDFLAGS} \$^

EOF
  fi

  cat <<EOF
.SUFFIXES: .ecpp .gif .jpg .css .js .cpp
ECPPC=$prefix/bin/ecppc
TNTNET=$prefix/bin/tntnet
CXXFLAGS+=-I$includedir -fPIC -O2
LDFLAGS+=-shared -L$libdir -ltntnet -lcxxtools

.ecpp.cpp:
	\${ECPPC} \${ECPPFLAGS} \${ECPPFLAGS_CPP} -o \$@ \$<
.gif.cpp:
	\${ECPPC} \${ECPPFLAGS} -m image/gif \${ECPPFLAGS_GIF} -b -o \$@ \$<
.jpg.cpp:
	\${ECPPC} \${ECPPFLAGS} -m image/jpg \${ECPPFLAGS_JPG} -b -o \$@ \$<
.png.cpp:
	\${ECPPC} \${ECPPFLAGS} -m image/png \${ECPPFLAGS_PNG} -b -o \$@ \$<
.ico.cpp:
	\${ECPPC} \${ECPPFLAGS} -m image/x-icon \${ECPPFLAGS_ICO} -b -o \$@ \$<
.css.cpp:
	\${ECPPC} \${ECPPFLAGS} -m text/css \${ECPPFLAGS_CSS} -b -o \$@ \$<
.js.cpp:
	\${ECPPC} \${ECPPFLAGS} -m application/javascript \${ECPPFLAGS_JS} -b -o \$@ \$<
EOF
}

project()
{
  P=$1
  mkdir $P || exit 1
  makefile $P >$P/Makefile
  template $P >$P/tntnet.conf
  properties $P >$P/tntnet.properties
  cat >$P/$P.ecpp <<EOF
<%pre>
// put your includes here
// #include "foo.h"
</%pre>
<%args>
// define the query parameters
// bar;
</%args>
<%session>
// define your session scope variables here
// std::string mySessionState;
</%session>
<%cpp>
// put your C++ code here
</%cpp>
<html>
 <head>
  <title>ecpp-application $P</title>
 </head>
 <body>
  <h1>$P</h1>
  <p>Hello world!</p>
 </body>
</html>
EOF
        cat <<EOF

Sample tntnet-project "$P" created.
To build change to the directory "$P" and run make.
To run the application execute "tntnet" there.
To view the page navigate your browser to "http://localhost:8000/".

EOF
}

autoproject()
{
  P=$1
  mkdir $P $P/include $P/include/my $P/lib $P/webapp || exit 1
  touch $P/NEWS $P/ChangeLog $P/AUTHORS $P/README

  C=$(echo $P|sed 's/[^A-Za-z0-9]/_/g')

  cat >$P/README <<EOF
This is a sample tntnet project using autotools.

The project is split into a library, which should contain the business logic
and a webapplication, which represents the presentation layer.

As an example a class "Foo" in the namespace "my" was generated and put into
the session scope of a web form.

To compile the application, run ./autogen.sh once, which generates a
configure script. Running the configure script generates Makefiles.
Running make, finally compiles the application.

To run the application, change to the webapp directory and enter "tntnet".
You find your webapplication on port 8000.

You may want to add your e-mail adress to the AC_INIT macro in configure.in.
EOF
  cat >$P/configure.in <<EOF
AC_INIT($P, 0.1, [])
AM_INIT_AUTOMAKE

abi_current=0
abi_revision=0
abi_age=0
sonumber=\${abi_current}:\${abi_revision}:\${abi_age}
AC_SUBST(sonumber)

AC_CONFIG_HEADERS([lib/config.h])
AC_CONFIG_SRCDIR([lib/foo.cpp])

AC_PROG_CXX
AC_PROG_LIBTOOL
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_RANLIB

AC_LANG(C++)
AC_CHECK_HEADER([tnt/tntnet.h], , AC_MSG_ERROR([tntnet headers not found]))
AC_CHECK_PROGS(ECPPC, [ecppc])
AC_CHECK_PROGS(TNTNET_CONFIG, [tntnet-config])

AC_CONFIG_FILES([Makefile
                 include/Makefile
                 lib/Makefile
                 webapp/Makefile])
AC_OUTPUT
EOF

  cat >$P/Makefile.am <<EOF
SUBDIRS = \
	include \
	lib \
	webapp
EOF

  cat >$P/include/Makefile.am <<EOF
nobase_include_HEADERS = \
	my/foo.h
EOF

  cat >$P/lib/Makefile.am <<EOF
AM_CPPFLAGS = -I\$(top_srcdir)/src -I\$(top_srcdir)/include

lib_LTLIBRARIES = lib$P.la

lib${C}_la_SOURCES = \
	foo.cpp
EOF

  cat >$P/webapp/Makefile.am <<EOF
AM_CPPFLAGS = -I\$(top_srcdir)/include

pkglib_LTLIBRARIES = $P.la

ecppSources = \\
	$P.ecpp

${C}_la_SOURCES = \\
	\$(ecppSources)

${C}_la_LIBADD = \$(top_builddir)/lib/lib$P.la
${C}_la_LDFLAGS = -module -ltntnet

noinst_DATA = tntnet.conf tntnet.properties
CLEANFILES = \$(ecppSources:.ecpp=.cpp) tntnet.conf tntnet.properties

SUFFIXES=.ecpp .jpg .cpp

.ecpp.cpp:
	\$(ECPPC) -I \$(top_srcdir)/web -o \$@ \$<
.jpg.cpp:
	\$(ECPPC) -b -m image/jpeg -o \$@ \$<

tntnet.properties:
	\$(TNTNET_CONFIG) --properties $P >\$@
tntnet.conf:
	( \$(TNTNET_CONFIG) --config=$P; echo CompPath .libs ) >\$@
EOF

  cat >$P/autogen.sh <<EOF
#! /bin/sh
# Regenerate the files autoconf / automake

libtoolize --force --automake

rm -f config.cache config.log
aclocal
autoheader
autoconf
automake -a
EOF

  cat >$P/include/my/foo.h <<EOF
/*
 * This is a example class for a C++ web project
 *
 */

#include <string>

namespace my
{
  class Foo
  {
    public:
      Foo()
        : intValue(0)
      { }

      int getIntValue() const
      { return intValue; }

      const std::string& getStringValue() const
      { return stringValue; }

      void setIntValue(int v)
      { intValue = v; }

      void addIntValue(int v)
      { intValue += v; }

      void setStringValue(const std::string& s)
      { stringValue = s; }

      // declare more Foo methods here
      // void f();

    private:
      int intValue;
      std::string stringValue;

  };

}
EOF

  cat >$P/lib/foo.cpp <<EOF
/*
 * This is a example class for a C++ web project
 *
 */

#include <my/foo.h>

namespace my
{
  // define your Foo methods here

/*
void Foo::f()
{
}
*/

}
EOF
  cat >$P/webapp/$P.ecpp <<EOF
<%pre>
// put your includes here
#include <my/foo.h>
</%pre>
<%args>

  // define the query parameters
  // bar;
  int intValue = 0;
  bool add;
  bool reset;

</%args>
<%session>

  // define your session scope variables here
  my::Foo foo;

</%session>
<%cpp>

  // put your C++ code here

  if (add)
  {
    log_debug("add");
    foo.addIntValue(intValue);
  }

  if (reset)
  {
    log_debug("reset");
    foo.setIntValue(0);
  }

  foo.setStringValue("Hello world!");

</%cpp>
<html>
 <head>
  <title>ecpp-application $P</title>
 </head>
 <body>
  <h1>$P</h1>
  <p><\$ foo.getStringValue() \$></p>
  <p>Value=<\$ foo.getIntValue() \$></p>

  <form method="post">
   <input type="text" name="intValue" value="<\$intValue\$>">
   <input type="submit" name="add" value="add">
   <input type="submit" name="reset" value="reset">
  </form>

 </body>
</html>
EOF

  chmod +x $P/autogen.sh

  cat <<EOF

Sample tntnet-project "$P" created.
Make sure, you have autoconf and automake installed.
To build change to the directory "$P" and run ./autogen.sh && ./configure && make.
To run the application execute "tntnet" in $P/webapp.
To view the page navigate your browser to "http://localhost:8000/".

EOF
}

if test $# -eq 0; then
    usage
fi

while test $# -gt 0; do
    case "$1" in
    -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
    *) optarg= ;;
    esac

    case "$1" in

    --version)
        echo 2.1
        exit 0
        ;;

    --help)
        usage
        ;;

    --cxxflags)
        echo -I$includedir
        ;;

    --libs)
        echo -L$libdir -ltntnet -lcxxtools
        ;;

    --makefile=*)
        makefile $optarg
        ;;

    --makefile)
        makefile
        ;;

    --config=*)
        template $optarg
        ;;

    --config)
        template
        ;;

    --properties=*)
        properties $optarg
        ;;

    --properties)
        properties $2
        shift
        ;;

    --project=*|-p=*)
        project $optarg
        ;;

    --project|-p)
        project $2
        shift
        ;;

    --autoproject=*|-A=*)
        autoproject $optarg
        ;;

    --autoproject|-A)
        autoproject $2
        shift
        ;;

    *)
        usage
        exit 1
        ;;
    esac
    shift
done

exit 0
