#! /bin/sh

prefix=/usr/local
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
  --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
<?xml version="1.0" encoding="UTF-8"?>
<!--
  This is the main configuration file for tntnet.

  You can find documentation about the parameters in the man page tntnet.xml(7)
  -->
<tntnet>
EOF
  if test -z "$1"
  then
    cat <<EOF
  <mappings>
    <!-- map /webapp/comp.* or /webapp/comp to comp@webapp -->
    <mapping>
      <target>\$2@\$1</target>
      <url>^/(.+)/([^.]+)(\..+)?</url>
    </mapping>
    <!-- map /comp.* or /comp to comp@comp -->
    <mapping>
      <target>\$1@\$1</target>
      <url>^/([^.]+)(\..+)?</url>
    </mapping>
  </mappings>
EOF
  else
    cat <<EOF
  <mappings>
    <!-- map / to $1@$1 -->
    <mapping>
      <target>$1@$1</target>
      <url>^/$</url>
    </mapping>
    <!-- map /comp.* or /comp to comp@$1 -->
    <mapping>
      <target>\$1@$1</target>
      <url>^/([^.]+)(\..+)?</url>
    </mapping>
  </mappings>
EOF
  fi

  cat <<EOF

  <!-- listen to a port (empty string means any local interface) -->
  <listeners>
    <listener>
      <port>8000</port>
    </listener>
  <!-- a certificate enables ssl -->
  <!--
    <listener>
      <port>8443</port>
      <certificate>tntnet.pem</certificate>
    </listener>
    -->
  </listeners>

  <logging>
    <rootlogger>INFO</rootlogger>

    <loggers>
      <logger>
        <category>tntnet</category>
        <level>INFO</level>
      </logger>
      <logger>
        <category>component.$1</category>
        <level>INFO</level>
      </logger>
    </loggers>

    <!--
    <file>tntnet.log</file>
    <maxfilesize>10M</maxfilesize>
    <maxbackupindex>2</maxbackupindex>
    -->

  </logging>

  <!-- <maxRequestSize>65536</maxRequestSize> -->
  <!-- <maxRequestTime>600</maxRequestTime> -->
  <!-- <user>tntnet</user> -->
  <!-- <group>tntnet</group> -->
  <!-- <dir>/</dir> -->
  <!-- <chrootdir>/var/safedir</chrootdir> -->
  <!-- <pidfile>/var/run/tntnet.pid</pidfile> -->
  <!-- <daemon>0</daemon> -->
  <!-- <minThreads>5</minThreads> -->
  <!-- <maxThreads>100</maxThreads> -->
  <!-- <threadStartDelay>10</threadStartDelay> -->
  <!-- <queueSize>1000</queueSize> -->
  <!--
  <compPath>
    <entry>path1</entry>
    <entry>path2</entry>
  </compPath>
   -->
  <!-- <bufferSize>16384</bufferSize> -->
  <!-- <socketReadTimeout>10</socketReadTimeout> -->
  <!-- <socketWriteTimeout>10000</socketWriteTimeout> -->
  <!-- <keepAliveTimeout>15000</keepAliveTimeout> -->
  <!-- <keepAliveMax>1000</keepAliveMax> -->
  <!-- <sessionTimeout>300</sessionTimeout> -->
  <!-- <listenBacklog>64</listenBacklog> -->
  <!-- <listenRetry>5</listenRetry> -->
  <!-- <enableCompression>no</enableCompression> -->
  <!-- <mimeDb>/etc/mime.types</mimeDb> -->
  <!-- <minCompressSize>1024</minCompressSize> -->
  <!-- <maxUrlMapCache>8192</maxUrlMapCache> -->
  <!-- <defaultContentType>text/html; charset=UTF-8</defaultContentType> -->
  <!-- <accessLog>/var/log/tntnet/access.log</accessLog> -->
  <!-- <errorLog>/var/log/tntnet/error.log</errorLog> -->
  <!-- <maxBackgroundTasks>5</maxBackgroundTasks> -->

</tntnet>
EOF
}

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

test: all
	\${TNTNET} tntnet.xml

$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.xml
  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.xml
CLEANFILES = \$(ecppSources:.ecpp=.cpp) tntnet.xml

SUFFIXES=.ecpp .jpg .cpp

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

tntnet.xml:
	( \$(SHELL) \$(TNTNET_CONFIG) --config=calc|awk '/<\/tntnet>/{print "  <compPath>\n    <entry>.libs</entry>\n  </compPath>"} {print}' ) >\$@
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.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 $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
