#! /bin/bash

# COOKIE=$(mcookie); grep -v V_GREP_ME $0 > /dev/shm/runme-$COOKIE.sh ; sleep 1; exec bash /dev/shm/runme-$COOKIE.sh
# TESTING=1

# Use this when R is build & installed and the package list 'work in progress'
# PKGDEBUG=1

PKG=R
VERSION=4.0.1
BUILD=0

# https://www.r-project.org/
# https://cran.r-project.org/mirrors.html
# CRANMIRROR=https://packages.othr.de/cran/
# A caching proxy under /project/retarded/rproxy
CRANMIRROR=http://platsch:8010/cran/$PKG-$VERSION-$BUILD/

PREFIX=/pkg/$PKG-$VERSION-$BUILD
if [ -n "$TESTING" ]; then PREFIX=/dev/shm/$PKG-$VERSION-$BUILD ; fi

# export GITHUB_PAT='5***b' 38 secret chars
. ./github_pat.source
if [ -z "$GITHUB_PAT" ] ; then
  echo "# Error: GITHUB_PAT is not set, build of 'dynverse/dyno' is supposed to fail."
  echo "#        Check the dvteam mails for 'personal access token'"
  exit 1
fi

# neither home nor /usr/local/package - but texlive kpsewhich for nghiavtr/BPSC
# mind: we need this path later on, since presumably Seurat or one of its
# dependencies screws up the PATH
PATH=/bin:/usr/bin:/usr/sbin:/usr/local/bin:/package/texlive/2015/bin

echo "# Ready player one."
date

set -xe
umask 022

BUILD_TMPDIR=/dev/shm/$PKG-$VERSION-$BUILD.build.tmp
test -d $BUILD_TMPDIR && rm -fr $BUILD_TMPDIR/build/velocyto_fixup
test -d $BUILD_TMPDIR && rm -r $BUILD_TMPDIR
mkdir -p $BUILD_TMPDIR/home
export TMPDIR=$BUILD_TMPDIR
export HOME=$BUILD_TMPDIR/home

exec </dev/null

mkdir -p $PREFIX
cat >$PREFIX/profile <<-EOF
	PATH=$PREFIX/bin:\$PATH
	PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig\${PKG_CONFIG_PATH:+:\$PKG_CONFIG_PATH}
	LD_LIBRARY_PATH=$PREFIX/lib\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}
	if [ -d $PREFIX/.compatlibs ]; then export LD_LIBRARY_PATH=$PREFIX/.compatlibs\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH} ; fi
	export PKG_CONFIG_PATH LD_LIBRARY_PATH
EOF
. $PREFIX/profile


NPROC=$(nproc)
export MAKEFLAGS="-j $NPROC"

BUILDDIR=$BUILD_TMPDIR/build
mkdir -p $BUILDDIR
cd $BUILDDIR

if [ -z "$PKGDEBUG" ]; then

# Start with some extra stuff. To keep the 'sf' package happy.

( # for 'dynverse/dyno', see UDUNITS2_INCLUDE, UDUNITS2_LIBS below
  UNITSVER=2.2.26
  # test -e udunits-$UNITSVER.tar.gz || wget --no-verbose ftp://ftp.unidata.ucar.edu/pub/udunits/udunits-$UNITSVER.tar.gz
  test -e udunits-$UNITSVER.tar.gz || cp /src/mariux/md5repo/5803837c6019236d24a9c9795cc8b462/udunits-2.2.26.tar.gz .
  test -d udunits-$UNITSVER        || tar -xf udunits-$UNITSVER.tar.gz
  cd udunits-$UNITSVER
  CFLAGS='-O2 -fPIC' \
  ./configure --prefix=$PREFIX --libdir=$PREFIX/lib --enable-shared=no
  make
  make install
)

# The rest is for 'sf', with 'spdep' as the real culprit.
# sf is a pain in the ass, as it carries tons of system dependencies (GDAL, PROJ, ...)
# https://github.com/r-spatial/sf - Simple Features for R
# ('Simple' in the sense of brainless I guess)
# OTOH its needed by monocle3, which is related to AG Mundlos & M. Spielmann, a Nature publication ...

(
  PROJVER=6.1.0
  # test -e proj-$PROJVER.tar.gz || wget --no-verbose http://download.osgeo.org/proj/proj-$PROJVER.tar.gz
  test -e proj-$PROJVER.tar.gz || cp /src/mariux/md5repo/4ec5d9240b0e290670886519f250946c/proj-6.1.0.tar.gz .
  test -d proj-$PROJVER || tar -xf proj-$PROJVER.tar.gz
  cd proj-$PROJVER

  ./configure \
  --prefix=$PREFIX \
  --libdir=$PREFIX/lib \
  --with-external-gtest=no

  make
  make install
)

(
  GEOSVER=3.7.2
  # test -e geos-$GEOSVER.tar.bz2 || wget --no-verbose http://download.osgeo.org/geos/geos-$GEOSVER.tar.bz2
  test -e geos-$GEOSVER.tar.bz2 || cp /src/mariux/md5repo/8caa4d19d311c1a78feb2f57505dc0e3/geos-3.7.2.tar.bz2 .
  test -d geos-$GEOSVER || tar -xf geos-$GEOSVER.tar.bz2
  cd geos-$GEOSVER

  ./configure \
  --prefix=$PREFIX \
  --libdir=$PREFIX/lib

  make
  make install
)

(
  GDALVER=2.4.1
  # test -e gdal-$GDALVER.tar.xz || wget --no-verbose http://download.osgeo.org/gdal/$GDALVER/gdal-$GDALVER.tar.xz
  test -e gdal-$GDALVER.tar.xz || cp /src/mariux/md5repo/ff98500aab063da563acade884518dfa/gdal-2.4.1.tar.xz .
  test -d gdal-$GDALVER || tar -xf gdal-$GDALVER.tar.xz
  cd gdal-$GDALVER

  export CFLAGS="-O2 -fPIC"
  export CXXFLAGS="-O2 -fPIC"
  ./configure \
  --prefix=$PREFIX \
  --libdir=$PREFIX/lib

  make
  make install
)

# ###########
# Now Build R

# test -e R-$VERSION.tar.gz || wget --no-verbose https://cran.r-project.org/src/base/R-4/R-4.0.1.tar.gz
test -e R-$VERSION.tar.gz || cp /src/mariux/md5repo/8d199d11865c202cf2bd006e7f32dab7/R-4.0.1.tar.gz .
test -d R-$VERSION        || tar -xf R-$VERSION.tar.gz
cd R-$VERSION

sed -i 's/en_GB/en_US/g' tests/reg-tests-3.R tests/reg-tests-3.Rout.save

./configure \
  --prefix=$PREFIX \
  --libdir=$PREFIX/lib \
  --with-pic \
  --with-recommended-packages \
  --enable-shared \
  --with-x \
  --enable-R-shlib \
  LDFLAGS=-Wl,-rpath,$PREFIX/lib/R/lib

export TZ=CEST  # some tests need timezone
make
make check
make install

cd $BUILDDIR

cat <<- RCODEXXX | Rscript -
	options(repos=structure(c(CRAN='$CRANMIRROR')))
	install.packages('BiocManager')
	install.packages('remotes') # or installs from github will fail.
	BiocManager::install() # this should update the 'base' packages
RCODEXXX


echo "# State of lib/R/library after initial setup:"
ls -la $PREFIX/lib/R/library

fi ### -z "$PKGDEBUG"

unset  DISPLAY # avoid warnings about 'RGL: unable to open X11 display'
export UDUNITS2_INCLUDE=$PREFIX/include
export UDUNITS2_LIBS=$PREFIX/lib


# List of packages
# Package names containing a '/' are treated as GitHub repositories
# SingleCellExperiment must come before aertslab/SCENIC, so just do all github stuff at the end

# Format hint:
# cat package_list | sed -e 's/\s\s*/\n/g' | sort -f | uniq | tr '\n' ' ' | fmt -w 120

cat <<- RCODEXXX > package_list
 abind acepack ACME ade4 AdequacyModel affy affyio affyPLM akima ALL annotate AnnotationDbi AnnotationForge aod
 ape apeglm arrayQualityMetrics ash assertthat AUCell bamsignals base64 base64enc batchelor BatchJobs BayesDA
 BBmisc bdsmatrix beadarray BeadDataPackR beanplot beeswarm bgmm BH bigmemory bigmemory.sri Biobase BiocGenerics
 BiocParallel biomaRt BioNet Biostrings biovizBase bit bitops boot bootstrap Boruta bpca BradleyTerry2 brew brglm
 BSgenome BSgenome.Ecoli.NCBI.20080805 bumphunter c060 C50 Cairo car caret Category caTools CellNOptR checkmate
 ChIPpeakAnno ChIPseeker chipseq chron circlize CircStats Ckmeans.1d.dp class clue cluster clusterProfiler
 CNEr coda codetools coin colorspace combinat corpcor corrgram corrplot cowplot crayon cummeRbund curl cvTools
 data.table DBI DelayedArray DelayedMatrixStats deldir DEoptimR DESeq DESeq2 devtools DEXSeq dichromat 
 digest DirichletMultinomial dismo DNAcopy doMC doParallel doRNG doSNOW dostats dplyr dtw dynamicTreeCut e1071
 earth easyRNASeq edgeR elasticnet energy entropy evaluate evd exactRankTests exomeCopy ExomeDepth fail fANCOVA
 fastcluster fastICA fastmatch FDb.InfiniumMethylation.hg19 fdrtool FField fields filehash flashClust foreach
 foreign formatR Formula futile.logger futile.options gbm gclus gcrma gdata genefilter GeneNet geneplotter
 genetics  GenomeInfoDb genomeIntervals GenomicAlignments GenomicFeatures GenomicRanges GEOquery
 getopt GGally ggbio ggm ggplot2 ggpubr git2r glasso Glimma glmnet GlobalAncova GlobalOptions globaltest gmp gnm
 GO.db GOstats GOTHiC gplots graph gRbase gridBase gridExtra gridSVG GSEABase GSEAlm gsl gsubfn gtable gtools Gviz
 h2o haplo.stats HardyWeinberg hash hdf5r hdi hdrcde hexbin hflights hgu95av2 hgu95av2.db hgu95av2cdf HiCcompare
 highr HiveR Hmisc HMM Homo.sapiens hsmm htmltools HTqPCR httpuv httr hwriter igraph illuminaio impute infotheo
 inline intervals ipred IRanges iterators itertools jsonlite kernlab KernSmooth knitr ks kSamples labeling Lahman
 lambda.r lars lattice latticeExtra lava lazyeval LEAP leaps LearnBayes lhs limma linprog lintr lme4 lmtest locfit
 longitudinal lpSolve lpSolveAPI LSD lumi magrittr manipulate mapproj maps maptools maptree markdown MASS MAST
 Matrix MatrixEQTL matrixStats mclust mda MEDIPS memoise meta MethylSeekR methylumi mgcv mice microbenchmark mime
 minfi minqa misc3d mitools mixtools mlegp modeltools monocle multcomp multicool multiHiCcompare multtest munsell
 muscle mvtnorm nleqslv nlme nloptr NMF nnet nor1mix numDeriv OmicCircos optparse org.Hs.eg.db OrganismDbi pamr
 party partykit pbapply pbkrtest pcalg pcaMethods penalizedSVM peperr PerfMeas pheatmap pkgmaker plotmo plotrix pls
 plus plyr ppcor pracma preprocessCore pROC prodlim profileModel proto proxy pwr qsea qtl quadprog quantreg QuasR
 qvalue qvcalc R.cache R.matlab R.methodsS3 R.oo R.utils R2HTML R6 randomForest randomGLM raster rbenchmark RBGL
 rbokeh RCircos RcisTarget RColorBrewer Rcpp RcppArmadillo RcppEigen RCurl registry relaimpo relimp remotes reshape
 reshape2 reticulate rex rFerns rggobi rgl Rgraphviz RGtk2 rhdf5 RhpcBLASctl Rhtslib rJava rjson RJSONIO rlecuyer
 RMariaDB rmarkdown rmeta RMySQL RNAseq123 rnaseqGene rngtools robustbase ROC ROCR roxygen2 rpart rpg RPostgres
 RPostgreSQL RRF Rsamtools RSQLite rstudioapi rtracklayer RUnit rversions RWeka RWekajars S4Vectors sandwich scales
 scalreg scatterplot3d scDD SCnorm scone SCORPIUS sda segmented sendmailR seqinr seqLogo seriation setRNG Seurat
 sf sfsmisc shape shiny ShortRead siggenes simpleaffy SingleCellExperiment sm snow snowfall snpStats som sp spam
 SparseM spatial splancs spls statmod stepPlr stringdist stringi stringr strucchange SummarizedExperiment SuppDists
 survey svMisc svTools tables TeachingDemos testthat TFBSTools TFMPvalue tgp TH.data tidyr tidyverse topGO
 TSP TxDb.Hsapiens.UCSC.hg19.knownGene VariantAnnotation vcd VennDiagram venneuler verification VGAM vsn waveslim
 WGCNA whisker xlsx xlsxjars XML xml2 xtable XVector yaml yeastCC zinbwave zipfR zlibbioc zoo
 aertslab/SCENIC aertslab/SCopeLoomR cole-trapnell-lab/leidenbase cole-trapnell-lab/monocle3 cole-trapnell-lab/RANNinf
 dynverse/dyno jokergoo/ComplexHeatmap jokergoo/EnrichedHeatmap nghiavtr/BPSC
RCODEXXX

# Note: compared to R-3.6.3-0, only DiffBind and GenomeGraphs where removed.
#
# missing:
# Scribe  # cole-trapnell-lab/Scribe/Scribe fails

cat <<- RCODEXXX | Rscript -
  XSAVE_PATH <- Sys.getenv('PATH')
  options(repos=structure(c(CRAN='$CRANMIRROR')))
  pkgs <- scan('package_list', what = character())
  for (pk in pkgs) {
    pa <- unlist(strsplit(pk, '/')); p <- pa[1]; if (! is.na(pa[2])) p <- pa[2]
    # there is no simple way to get rid of the error message, so avoid mimimi...
    cat('* if there is no package, install it - errors here are part of the test!\n')
    chk <- NULL; try(chk <- find.package(p))
    if (is.null(chk)) {
      cat( sprintf('* About to install: %s\n', pk), file='work_monitor_list', append = TRUE)
      BiocManager::install(pk, Ncpus = $NPROC, update = FALSE)
      ret <- library(p, character.only = TRUE, logical.return = TRUE)
      if (! ret) q(save = "no", status = 2)
      # the logic fails for 'cole-trapnell-lab/cicero-release', fixed below
      detach( paste("package", p, sep = ":"), unload = TRUE, character.only=TRUE)
      if (Sys.getenv('PATH') != XSAVE_PATH) {
        cat( sprintf('*** PATH SCREWUP OCCURED (package %s)\n', pk))
        cat( sprintf('*** expected: %s\n', XSAVE_PATH))
        cat( sprintf('*** now:      %s\n', Sys.getenv('PATH')))
      }
      Sys.setenv(PATH = XSAVE_PATH)
      cat( sprintf('* REALY_DONE with: %s\n', pk))
    } else {
      cat( sprintf('* ALREADY_DONE with: %s\n', pk))
    }
  }
RCODEXXX

# simple test: can everything be found?
cat <<- RCODEXXX | Rscript -
  pkgs <- scan('package_list', what = character())
  for (pk in pkgs) {
    pa <- unlist(strsplit(pk, '/')); p <- pa[1]; if (! is.na(pa[2])) p <- pa[2]
    chk <- NULL; try(chk <- find.package(p))
    if (is.null(chk)) {
      cat( sprintf('* ERROR: Missing package: %s\n', pk))
      q(save = "no", status = 3)
    }
  }
RCODEXXX

# stress test: load all packages (uses 4G, claims 16G)
cat <<- RCODEXXX | Rscript -
  pkgs <- scan('package_list', what = character())
  for (pk in pkgs) {
    pa <- unlist(strsplit(pk, '/')); p <- pa[1]; if (! is.na(pa[2])) p <- pa[2]
    ret <- library(p, character.only = TRUE, logical.return = TRUE)
    if (! ret) {
      cat( sprintf('* ERROR: Failed to load package/library: %s\n', pk))
      q(save = "no", status = 4)
    }
  }
RCODEXXX

# do 'cole-trapnell-lab/cicero-release' seperately
echo "BiocManager::install('cole-trapnell-lab/cicero-release', update = FALSE)" | Rscript -

# rstudios rsession does a lot of magic to detect the true R binary, thus bypassing
# our friendly 'hints' from the wrapper.
# tell lib/R/library/sf/libs/sf.so about lib -- yes it's the beloved sf package again!
# the original rpath is only set to /pkg/R-x.y.z-0/lib/R/lib, add /pkg/R-x.y.z-0/lib.
# to be fixed in next rstudio build

patchelf --set-rpath $PREFIX/lib/R/lib:$PREFIX/lib \
         $PREFIX/lib/R/library/sf/libs/sf.so

# finally a source build, this is intended to provide a clean velocyto.R package for G. Pacini.
# Right now he needs to add /package/voreen/.compatlibs for unused (!) boost libraries.

# velocyto.R uses an inappropriate makefile and has a silly multitreading issue

cd $BUILDDIR
mkdir -p velocyto_fixup
cd velocyto_fixup

git clone https://github.com/velocyto-team/velocyto.R
cd velocyto.R
git checkout 0.6 --force
git clean -dffx

mv src/Makevars src/Makevars.weird
# yields just -fopenmp, whis won't work on macs with clang
echo 'PKG_CXXFLAGS=-Wall $(SHLIB_OPENMP_CXXFLAGS)' > src/Makevars

# intercept the inane 'grab all cores' policy
# defaultNCores <- function() { parallel::detectCores(logical=F) }

cp -p R/momentum_routines.R R/momentum_routines.R.orig
sed -e '/^defaultNCores/ d' -i R/momentum_routines.R
cat <<__NCores_HACK >> R/momentum_routines.R
defaultNCores <- function() {
  env <- Sys.getenv('VELOCYTO_CORES')
  if (env != "") { return(as.integer(env)) }
  parallel::detectCores(logical=F)
}
__NCores_HACK

R CMD INSTALL .

echo "# Game over ..."
date

exit