#!/bin/sh
#############################################################################
# $Id$
#   Create new CMake project which uses prebuilt NCBI C++ toolkit from a sample
#   Author: Andrei Gourianov, gouriano@ncbi
#############################################################################
initial_dir=`pwd`
script_name=`basename $0`
script_dir=`dirname $0`
script_dir=`(cd "${script_dir}" ; pwd)`
cd "$initial_dir"
tree_root=`pwd`

build_root=$NCBI
build_pfx="c++.cmake."
build_def="stable"
build_dir="${build_pfx}${build_def}"

repository="https://svn.ncbi.nlm.nih.gov/repos/toolkit/trunk/c++"
rep_inc="include"
rep_src="src"
rep_sample="sample"
prj_prj="CMakeLists.txt"
cfg_cfg="configure.sh"
############################################################################# 
Usage()
{
    cat <<EOF
USAGE:
  $script_name <name> <type> [builddir] [OPTIONS] 
SYNOPSIS:
  Create new CMake project which uses prebuilt NCBI C++ toolkit from a sample.
ARGUMENTS:
  --help       -- print Usage
  <name>       -- project name (destination directory)
  <type>       -- project type
  builddir     -- root directory of the pre-built NCBI C++ toolkit
                  default: $build_def
OPTIONS:
  --noconfig   -- skip configuring build
EOF
if test -z "$1"; then
  echo
  echo The following project types are available:
  svn list -R $repository/$rep_src/$rep_sample | while IFS= read -r line; do
    case "$line" in */ )
      count=`echo $line | tr -cd '/' | wc -c`
      if [ $count -eq 2 ]; then
        prj=${line%?}
        case "$prj" in 
        app/alnmgr)         echo "  app/alnmgr          an application that uses Alignment Manager";;
        app/asn)            echo "  app/asn             an application that uses ASN.1 specification";;
        app/basic)          echo "  app/basic           a simple application";;
        app/blast)          echo "  app/blast           a BLAST application";;
        app/cgi)            echo "  app/cgi             a CGI application";;
        app/connect)        echo "  app/connect         a Usage report logging";;
        app/dbapi)          echo "  app/dbapi           a DBAPI application";;
        app/deployable_cgi) echo "  app/deployable_cgi  a CD-deployable CGI application";;
        app/eutils)         echo "  app/eutils          an eUtils client application";;
        app/http_session)   echo "  app/http_session    an application that uses CHttpSession";;
        app/lds)            echo "  app/lds             an application that uses local data store";;
        app/multicmd)       echo "  app/multicmd        a simple command-based application";;
        app/netcache)       echo "  app/netcache        an application that uses NetCache";;
        app/netschedule)    echo "  app/netschedule     an NCBI GRID (NetSchedule) application";;
        app/objects)        echo "  app/objects         an application that uses ASN.1 objects";;
        app/objmgr)         echo "  app/objmgr          an application that uses Object Manager";;
        app/sdbapi)         echo "  app/sdbapi          a Simple-DBAPI application";;
        app/serial)         echo "  app/serial          a data serialization application";;
        app/soap)           echo "  app/soap/client     a SOAP client"
                            echo "  app/soap/server     a SOAP server";;
        app/unit_test)      echo "  app/unit_test       a Boost-based unit test application";;
        lib/asn_lib)        echo "  lib/asn_lib         a static library from ASN.1 specification";;
        lib/basic)          echo "  lib/basic           a simple static library";;
        lib/dtd)            echo "  lib/dtd             a static library from DTD specification";;
        lib/jsd)            echo "  lib/jsd             a static library from JSON Schema specification";;
        lib/xsd)            echo "  lib/xsd             a static library from XML Schema specification";;
        *)                  echo "  $prj";;
        esac 
      fi
      ;;
    esac
  done
fi
echo " "
}

Error()
{
  Usage notype
  if test -n "$1"; then
    echo ----------------------------------------------------------------------
    echo ERROR: $@ 1>&2
  fi
  cd "$initial_dir"
  exit 1
}

Get_build_dir()
{
  all=`ls $NCBI | grep ${build_pfx} | sed "s/${build_pfx}//g"`
  while true; do
    cat <<EOF

Please pick a stability level
Available:

$all

EOF
    read -p "Desired stability (default = ${build_def}): " stability
    test -n "$stability"  ||  stability=${build_def}
    builddir=${build_root}/${build_pfx}${stability}
    if [ -d ${builddir} ]; then
      break
    fi
  done
}

#----------------------------------------------------------------------------
if [ $# -eq 0 ]; then
  do_help="yes"
fi
pos=0
unknown=""
while [ $# -ne 0 ]; do
  case "$1" in 
    --help|-help|help|-h)
      do_help="yes"
    ;; 
    --noconfig)
      noconfig="yes"
    ;;
    *) 
      if [ $pos -eq 0 ]; then
        prj_name=$1
      elif [ $pos -eq 1 ]; then
        prj_type=$1
      elif [ $pos -eq 2 ]; then
        toolkit=$1
      else
        unknown="$unknown $1"
      fi
      pos=`expr $pos + 1`
      ;; 
  esac 
  shift 
done 


if [ -n "$do_help" ]; then
    Usage
    exit 0
fi
if [ -n "$unknown" ]; then
  Error "Unknown options: $unknown" 
fi
if [ -z "$prj_name" ]; then
  Error "Mandatory argument 'name' is missing"
fi
if [ -z "$prj_type" ]; then
  Error "Mandatory argument 'branch' is missing"
fi
if [ -e $prj_name ]; then
  Error File or directory $prj_name already exists
fi
if [ -z "$toolkit" ]; then
  Get_build_dir
else
  if [ -d "$toolkit" ]; then
    builddir="$toolkit"
  elif [ -d "${build_root}/$toolkit" ]; then
    builddir="${build_root}/$toolkit"
  elif [ -d "${build_root}/${build_pfx}$toolkit" ]; then
    builddir="${build_root}/${build_pfx}$toolkit"
  fi
fi
if [ ! -d "$builddir" ]; then
  echo "----------------------------------------------------------------------"
  if [ -z "$toolkit" ]; then
    echo "ERROR:  Directory not found: $builddir" 1>&2
  else
    echo "ERROR:  Directory not found: $toolkit" 1>&2
  fi
  echo "Try one of these:"
  ls $NCBI | grep ${build_pfx} | sed "s/${build_pfx}//g"
  exit 1
fi

prebuilt_path="?"
prebuilds=""
if [ ! "$noconfig" = "yes" ]; then
    tmp=`ls ${builddir}`
    if [ -n "$tmp" ]; then
        for d in $tmp; do
            if [ -f ${builddir}/$d/cmake/buildinfo ]; then
                prebuilds="${prebuilds} $d"
            fi
	    done
        for d in $prebuilds; do
            build_def=$d
            break
        done
        all=`echo $prebuilds | tr ' ' '\n'`
        while true; do
            cat <<EOF

Please pick a build configuration
Available:

$all

EOF
            read -p "Desired configuration (default = ${build_def}): " build_config
            test -n "$build_config"  ||  build_config=${build_def}
            prebuilt_path=${build_config}
            if [ -d ${builddir}/${prebuilt_path} ]; then
                break
            fi
        done
    fi
fi

mkdir -p $prj_name
if [ ! -d $prj_name ]; then
  Error Failed to create directory $prj_name
fi
cd $prj_name

#----------------------------------------------------------------------------
#path=`echo $prj_type | tr "/" " "`
#for d in $path; do
#  echo ---- $d
#done

mkdir $rep_inc 2>/dev/null
mkdir $rep_src 2>/dev/null
svn co $repository/$rep_inc/$rep_sample/$prj_type $rep_inc 1>/dev/null 2>/dev/null
svn co $repository/$rep_src/$rep_sample/$prj_type $rep_src 1>/dev/null
find . -name ".svn" -exec rm -rf {} \; 1>/dev/null 2>/dev/null
find $rep_src -name "Makefile.*" -exec rm -rf {} \; 1>/dev/null 2>/dev/null

# create configure script
host_os=`uname`
#if test $host_os = "Darwin"; then
cmake_cfg="cmake-cfg-unix.sh"

{
  echo "#!/bin/sh"
  echo "script_dir=\`dirname \$0\`"
  echo "script_name=\`basename \$0\`"
  echo "exec $builddir/src/build-system/cmake/$cmake_cfg --rootdir=\$script_dir --caller=\$script_name \"\$@\""

} > $cfg_cfg
chmod a+x $cfg_cfg

# modify CMakeLists.txt
{
  echo "cmake_minimum_required(VERSION 3.15)"
  echo "project($prj_name)"
  echo "include($builddir/src/build-system/cmake/CMake.NCBItoolkit.cmake)"
  echo "NCBI_add_subdirectory($rep_src)"
} > $prj_prj

echo "Created project $prj_name"
echo "To configure:  cd $prj_name; ./$cfg_cfg <arguments>"
echo "For help:      cd $prj_name; ./$cfg_cfg --help"
if [ ! "$noconfig" = "yes" ]; then
    echo ----------------------------------------------------------------------
    ./$cfg_cfg --with-prebuilt=${prebuilt_path}
fi
cd "$initial_dir"
