#! /bin/sh

# Adapted from the ocamlnet configure script.

#######################################################################
# Helpers:

test_binary () {
  # $1: the name of the binary
  echo -n "Checking for $1 ... "
  if which "$1" >/dev/null 2>/dev/null; then
    echo "found"
    return 0
  else
    echo "not found"
    return 1
  fi
}

fail_binary () {
  echo
  echo "Required command '$1' not found!"
  [ -z "$2" ] || echo "===> $2"
  exit 1
}

check_binary () {
  # $1: the name of the binary
  # $2: an URL
  if test_binary $1; then
      return
  else
      fail_binary $1 $2
  fi
}


test_library () {
  # $1: the name of the library (findlib)
  echo -n "Checking for $1 ... "
  if ocamlfind query $1 >/dev/null 2>/dev/null; then
    echo "found"
    return 0
  else
    echo "not found"
    return 1
  fi
}

fail_library () {
  echo
  echo "Required library $1 not found!"
  [ -z "$2" ] || echo "===> $2"
  exit 1
}

check_library () {
  # $1: the name of the library (findlib)
  # $2: an URL
  if test_library $1; then
      return
  else
      fail_library $1 "$2"
  fi
}

#######################################################################
# Defaults

#--- Options ---
# value 0: off
# value 1: on
# defaults:

set_defaults () {
    name="ocsigenserver"
    enable_natdynlink=1
    enable_debug=1
    enable_annot=1
		enable_profiling=0
    with_sqlite=1
    with_pgsql=1
    with_camlzip=1
    with_dbm=1
    prefix="/usr/local"
    bindir=""
    logdir=""
    libdir=""
    mandir=""
    docdir=""
    sysconfdir="/etc/\$(PROJECTNAME)"
    staticpagesdir="/var/www/\$(PROJECTNAME)"
    uploaddir="/tmp"
    datadir="/var/lib/\$(PROJECTNAME)"
    temproot=""
    root=""
    ocsigen_user="www-data"
    ocsigen_group="www-data"
}

set_defaults
my_pwd=`dirname $0`
version=`head -n 1 $my_pwd/VERSION`
full_pwd=`pwd`

########################################################################
## Option parsing

## Which options exist? eoptions for enable/disable, woptions for with/without:
eoptions="debug annot profiling natdynlink"
woptions="pgsql sqlite dbm camlzip"

print_options () {
	for opt in $eoptions; do
		e="o=\$enable_$opt"
		eval "$e"
		uopt=`echo $opt | sed -e 's/_/-/g'`
		if [ $o -gt 0 ]; then
			echo "    --enable-$uopt"
		else
			echo "    --disable-$uopt"
		fi
	done
	for opt in $woptions; do
		e="o=\$with_$opt"
		eval "$e"
		uopt=`echo $opt | sed -e 's/_/-/g'`
		if [ $o -gt 0 ]; then
			echo "    --with-$uopt"
		else
			echo "    --without-$uopt"
		fi
	done
        case "$bindir" in
            "") bindir2="<prefix>/bin";;
            *) bindir2=$bindir;;
        esac

        case "$logdir" in
            "") logdir2="<prefix>/var/log/<name>";;
            *) logdir2=$logdir;;
        esac

        case "$libdir" in
            "") libdir2="\$(shell \${OCAMLFIND} printconf destdir)";;
            *) libdir2=$libdir;;
        esac

        case "$mandir" in
            "") mandir2="<prefix>/share/man/man1";;
            *) mandir2=$mandir;;
        esac

        case "$docdir" in
            "") docdir2="<prefix>/share/doc/\$(PROJECTNAME)";;
            *) docdir2=$docdir;;
        esac

	echo "    --name $name"
	echo "    --root $root"
	echo "    --temproot $temproot"
	echo "    --prefix $prefix"
	echo "    --ocsigen-user $ocsigen_user"
	echo "    --ocsigen-group $ocsigen_group"
	echo "    --bindir $bindir2"
        echo "    --libdir $libdir2"
	echo "    --sysconfdir $sysconfdir"
	echo "    --mandir $mandir2"
	echo "    --docdir $docdir2"
	echo "    --logdir $logdir2"
	echo "    --staticpagesdir $staticpagesdir"
	echo "    --uploaddir $uploaddir"
	echo "    --datadir $datadir"
	echo "    --commandpipe $commandpipe"
}


usage () {
	set_defaults
	cat <<_EOF_ >&2
usage: ./configure [ options ]

  --enable-debug,	--disable-debug		Enable/disable debug output
  --enable-annot,	--disable-annot		Enable/disable .cmt{,i} files generation
  --enable-profiling,	--disable-profiling	Enable/disable profiling
  --enable-natdynlink,	--disable-natdynlink	Enable/disable nativecode dynamic linking

  --with-sqlite,	--without-sqlite	Compile ocsipersist with SQLite for persistent storage
  --with-pgsql,	--without-pgsql		Compile ocsipersist with PostgreSQL for persistent storage
  --with-dbm,		--without-dbm		Compile ocsipersist with DBM for persistent storage
  --with-camlzip,	--without-camlzip	Compile deflatemod extension, requires camlzip

  --name NAME		The name of the server binary and ocamlfind package.

  --ocsigen-user NAME	The name of the ocsigen user
  --ocsigen-group NAME	The name of the ocsigen group

  --root DIR		Root directory to install the package, every other options are relatives to this path. (usually /)
  --temproot DIR	Temporary root directory to install the package (usually always "" but for package makers)
  --prefix DIR		Subdirectory where to install binaries and libs (usually /usr or /usr/local)

  --bindir DIR		Install binaries into this directory
  --libdir DIR		Common directory for Ocsigen server's libraries

  --sysconfdir DIR	Create configuration files in this directory
  --mandir DIR		Install man pages in this directory
  --docdir DIR		Install documentation in this directory

  --logdir DIR		Use this directory for Ocsigen's logs
  --datadir DIR		The directory for data written by the server

  --staticpagesdir DIR	Install default static pages in this directory
  --uploaddir DIR	By default, files will be uploaded in this directory

  --commandpipe FILE	The name of the named pipe used to command the server

Defaults are:

_EOF_
	print_options >&2
	exit 1
}


check_eopt () {
	for x in $eoptions; do
		if [ "$x" = "$1" ]; then
			return 0
		fi
	done
	echo "Unknown option: $1" >&2
	exit 1
}


check_wopt () {
	for x in $woptions; do
		if [ "$x" = "$1" ]; then
			return 0
		fi
	done
	echo "Unknown option: $1" >&2
	exit 1
}

echo "\n\tWelcome to Ocsigen server, version $version.\n" >&2

while [ "$#" -gt 0 ]; do
	case "$1" in
		--enable-*)
			opt=`echo "$1" | sed -e 's/--enable-//' -e 's/-/_/g'`
			check_eopt "$opt"
			eval "enable_$opt=2"
			shift
			;;
		--disable-*)
			opt=`echo "$1" | sed -e 's/--disable-//' -e 's/-/_/g'`
			check_eopt "$opt"
			eval "enable_$opt=-1"
			shift
			;;
		--with-*)
			opt=`echo "$1" | sed -e 's/--with-//' -e 's/-/_/g'`
			check_wopt "$opt"
			eval "with_$opt=2"
			shift
			;;
		--without-*)
			opt=`echo "$1" | sed -e 's/--without-//' -e 's/-/_/g'`
			check_wopt "$opt"
			eval "with_$opt=-1"
			shift
			;;
		--root)
			root="$2"
			shift
			shift
			;;
		--temproot)
			temproot="$2"
			shift
			shift
			;;
		--prefix)
			prefix="$2"
			shift
			shift
			;;
                --bindir)
                        bindir="$2"
                        shift
                        shift
                        ;;
                --logdir)
                        logdir="$2"
                        shift
                        shift
                        ;;
                --libdir)
                        libdir="$2"
                        shift
                        shift
                        ;;
		--mandir)
			mandir="$2"
			shift
			shift
			;;
		--docdir)
			docdir="$2"
			shift
			shift
			;;
		--staticpagesdir)
			staticpagesdir="$2"
			shift
			shift
			;;
		--sysconfdir)
			sysconfdir="$2"
			shift
			shift
			;;
		--uploaddir)
			uploaddir="$2"
			shift
			shift
			;;
		--datadir)
			datadir="$2"
			shift
			shift
			;;
		--name)
			name="$2"
			shift
			shift
			;;
		--ocsigen-user)
			ocsigen_user="$2"
			shift
			shift
			;;
		--ocsigen-group)
			ocsigen_group="$2"
			shift
			shift
			;;
		--commandpipe)
			commandpipe="$2"
			shift
			shift
			;;
		*)
                        echo "Unknown option: $1" >&2
			usage
	esac
done

case "$bindir" in
  "") bindir="$prefix/bin";;
esac

case "$logdir" in
  "") logdir="/var/log/\$(PROJECTNAME)";;
esac

case "$libdir" in
  "") libdir="\$(shell \${OCAMLFIND} printconf destdir)";;
  *) libdir=$root$libdir
esac

case "$mandir" in
  "") mandir="$prefix/share/man/man1";;
esac

case "$docdir" in
  "") docdir="$prefix/share/doc/\$(PROJECTNAME)";;
esac

case "$commandpipe" in
  "") commandpipe="/var/run/\$(PROJECTNAME)_command";;
esac



check_binary ocamlc "See: http://www.ocaml.org/"

check_ocamlversion () {

  echo -n "Checking for OCaml version... "
  version=`ocamlc -version`
  echo $version
  n1=`echo $version | sed 's/^\([0-9][0-9]*\)\..*$/\1/'`
  n2=`echo $version | sed 's/^[0-9][0-9]*\.\([0-9][0-9]*\)\..*$/\1/'`
  # n3=`echo $version | sed 's/^[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)\..*$/\1/'`
  if [ $n1 -eq 3 ] && [ $n2 -lt 12 ]; then
      echo;
      echo "OCaml >= 3.12 is required. Aborting.";
      exit 1;
  fi

}

check_ocamlversion

check_binary ocamlfind "See: http://projects.camlcity.org/projects/findlib.html"

check_library react "See: http://erratique.ch/software/react"
check_library ssl "See: http://sourceforge.net/projects/savonet/files/ocaml-ssl"

check_library lwt "See: http://ocsigen.org/lwt"
check_library lwt.unix  "Missing support for 'unix' in lwt."
check_library lwt_react   "See: http://ocsigen.org/lwt"
check_library lwt_ssl   "See: http://ocsigen.org/lwt"
check_library lwt_log   "See: http://ocsigen.org/lwt"

check_library netstring \
    "See ocamlnet: http://projects.camlcity.org/projects/ocamlnet.html"
check_library netstring-pcre \
    "See ocamlnet: http://projects.camlcity.org/projects/ocamlnet.html"
check_library netsys \
    "See ocamlnet: http://projects.camlcity.org/projects/ocamlnet.html"

check_library pcre "See: http://ocaml.info/home/ocaml_sources.html"
check_library cryptokit "See: http://pauillac.inria.fr/~xleroy/software.html#cryptokit"

check_library tyxml "See: http://ocsigen.org/tyxml/"
check_library xml-light "See: https://github.com/ncannasse/xml-light"

# Check PostgreSQL
case "$with_pgsql" in
 1) if test_library pgocaml; then with_pgsql=1; else with_pgsql=0; fi;;
 2) check_library pgocaml "https://github.com/darioteixeira/pgocaml";;
esac

# Check Sqlite3
case "$with_sqlite" in
 1) if test_library sqlite3; then with_sqlite=1; else with_sqlite=0; fi;;
 2) check_library sqlite3 "See: http://ocaml.info/home/ocaml_sources.html";;
esac

# Check dbm
if [ "$with_dbm" -gt 0 ]; then
    if test_library dbm; then
	echo -n
    elif [ "$with_dbm" -gt 1 ]; then
	fail_library dbm
    else
        with_dbm=0
    fi
fi

# Check Camlzip
if [ "$with_camlzip" -gt 0 ]; then
    if test_library camlzip; then
	zipname=camlzip
    elif test_library zip; then
	zipname=zip
    elif [ "$with_camlzip" -gt 1 ]; then
	fail_library camlzip "https://forge.ocamlcore.org/projects/camlzip/"
    else
	with_camlzip=0
    fi
fi

# Check rlwrap or ledit
if test_binary rlwrap; then
    rlwrap=rlwrap
elif test_binary ledit; then
    rlwrap=ledit
else
    rlwrap=
fi

######################################################################
# Summary

echo
echo "Effective options:"
print_options
echo


#Convert 0/1 values to YES/NO
if [ $enable_debug -gt 0 ] ; then
	enable_debug="YES"
else
	enable_debug="NO"
fi
if [ $enable_annot -gt 0 ] ; then
	enable_annot="YES"
else
	enable_annot="NO"
fi
if [ $enable_profiling -gt 0 ] ; then
	enable_profiling="YES"
else
	enable_profiling="NO"
fi
if [ $enable_natdynlink -gt 0 ] ; then
	enable_natdynlink="YES"
else
	enable_natdynlink="NO"
fi
if [ $with_dbm -gt 0 ] ; then
	with_dbm="YES"
else
	with_dbm="NO"
fi
if [ $with_sqlite -gt 0 ] ; then
	with_sqlite="YES"
else
	with_sqlite="NO"
fi
if [ $with_pgsql -gt 0 ] ; then
	with_pgsql="YES"
else
	with_pgsql="NO"
fi
if [ $with_camlzip -gt 0 ] ; then
	with_camlzip="YES"
else
	with_camlzip="NO"
fi

ocamlinclude=`ocamlfind printconf stdlib`

######################################################################
# Write Makefile.conf

echo "Writing Makefile.config"
cat <<_EOF_ > $my_pwd/Makefile.config

# The name of the server, the ocamlfind package, etc.
PROJECTNAME := $name

#### External binaries ####

OCAMLFIND := ocamlfind
OCAMLLEX  := ocamllex
OCAMLMKLIB:= ocamlmklib
CHOWN     := chown
CHMOD     := chmod
INSTALL   := install
CC        := gcc

# optional
RLWRAP    := $rlwrap


### Options ###

# User who will run Ocsigen server (not root) (eg, for debian, www-data)
# (This user must exist on your system)
OCSIGENUSER := $ocsigen_user

# group who will run Ocsigen server (not root) (eg, for debian, www-data)
# (This group must exist)
OCSIGENGROUP := $ocsigen_group

# Do you want deflatemod? YES/NO (requires camlzip)
CAMLZIP:=$with_camlzip

# The name of camlzip package:
CAMLZIPNAME:=$zipname

# Do you want ocsipersist with sqlite? YES/NO
OCSIPERSISTSQLITE:=$with_sqlite

# Do you want ocsipersist with pgsql? YES/NO
OCSIPERSISTPGSQL:=$with_pgsql

# Do you want ocsipersist with dbm? YES/NO
OCSIPERSISTDBM:=$with_dbm

# Do you want debugging information (-g) ? YES/NO
DEBUG:=$enable_debug

# Do you want annot files (-bin-annot) ? YES/NO
ANNOT:=$enable_annot

# Profiling (always put NO here - but if you want to debug ocsigen):
PROFILING:=$enable_profiling



### Paths ###

# Temporary root directory to install the package (usually always "" but for package makers)
TEMPROOT := $temproot

# Do you want to use dynamic linking for native code? YES/NO
NATDYNLINK:=$enable_natdynlink

# The directory for ocsigen server (binary):
BINDIR := $root$bindir

# The directory for ocsigen manpage:
MANDIR := $root$mandir

# Where to install the libraries
LIBDIR := $libdir

# ocsigen's logs:
LOGDIR := $root$logdir

# Config files:
CONFIGDIR := $root$sysconfdir

# Where to put static pages:
STATICPAGESDIR := $root$staticpagesdir

# Where to put dynamic data:
DATADIR := $root$datadir

# Default directory for file upload:
UPLOADDIR := $root$uploaddir

# Where to put Ocsigen documentation:
DOCDIR := $root$docdir

# The name of the named pipe used to command the server
COMMANDPIPE := $root$commandpipe

# The source directory
SRC := $full_pwd

include \$(SRC)/Makefile.options
_EOF_

######################################################################
# Finish

echo
echo
echo "Please check Makefile.config."
echo
echo "You can now compile Ocsigen Server by invoking:"
echo
echo "   make"
echo "   make doc"
echo
echo "You may want to test the server before installation:"
echo
echo "   make run.local"
echo "   make run.opt.local"
echo
echo "Finally, if you want system-wide install, (become root if needed and) do:"
echo
echo "   make install"
echo "   make install.doc"
echo
