#!/usr/bin/env bash
set -e

# mithril app builder
# (c) rodolfo lp 2019
# network required for closure compiler

function aggregate() {

  echo "👉 Aggregating folder ${1} recursively"
  # Create Aggregated Libraries
  for filename in ${1}/**/*.js; do

    if [[ -f ${filename} ]]; then

      FILEFOLDER="$(
        cd "$(dirname "$filename")" >/dev/null 2>&1
        pwd -P
      )"

      PARENTFOLDER=$(basename "$FILEFOLDER")

      fname=$(basename "$filename")
      fname="${fname%.*}"

      if [[ "${fname}" == "main" && ${PARENTFOLDER} == "src" ]]; then
        echo "- main is handled separately"
      else
        echo "- Adding module ${fname} from ${PARENTFOLDER}"

      echo "requireRegister(M${i}, (exports, require, module) => {" >>"${2}"
        cat "${filename}" >>"${2}"

        echo >>"${2}"
        echo }\)\; >>"${2}"
      fi
      i=$((i + 1))

    else
      echo "- No third party libraries found in ${PROJLIB}."
    fi
  done
}

function aggregateStyle() {

  FILESTRING=$(eval echo "${1}/*.css")
  FILES=($FILESTRING)

  echo "👉 Aggregating styles in $1"

  for filename in "${FILES[@]}"; do
    if [[ -f $filename ]]; then
      fname=$(basename "$filename")
      fname="${fname%.*}"
      echo "- including ${BUILDTYPE} ${NAME} style [${fname}]"
      cat "${filename}" >>"${BUILDDIR}/${BUILDTYPE}.css"
    fi
  done
}

function obfuscateModules() {

  echo "👉 Obfuscating modules in ${1}"

  for filename in ${1}/**/*.js; do

    if [[ -f ${filename} ]]; then

      FILEFOLDER="$(
        cd "$(dirname "$filename")" >/dev/null 2>&1
        pwd -P
      )"
      PARENTFOLDER=$(basename "$FILEFOLDER")

      fname=$(basename "$filename")
      fname="${fname%.*}"

      if [[ "$2" -eq "1" ]]; then
        fname="${PARENTFOLDER}.${fname}"
      fi

      md5=$(echo -n ${fname} | md5sum - | cut -b 1-32)

      echo "- parsing ${fname} ... index ${i} ... md5 ${md5}"

      asig="${asig}M${i},"
      valu=${valu}\"${fname}\",
      valumd5=${valumd5}\"${md5}\",

      # require("mitril") => require(M34)
      buscar="require(\"${fname}\")"
      cambiar="require(M${i})"

      # echo "= buscar ${buscar} cambiar ${cambiar}"

      #     sed -i "" -e "s/${buscar}/${cambiar}/g" "${BUILDDIR}/${BUILDTYPE}.rx.js"
      sed -i -e "s/${buscar}/${cambiar}/g" "${BUILDDIR}/${BUILDTYPE}.rx.js"

      i=$((i + 1))
    fi
  done
}

if [[ ! -d "${TEMPDEST}" ]]; then
  echo "! Init script not executed."
  exit 6
fi

if [[ -z "${BUILDDIR}" ]]; then
  echo "! Init script not executed."
  exit 7
fi

# For using recursive directory search(requires bash v4+)
shopt -s globstar

PROJROOT=${SOURCEROOT}/${NAME}
PROJSRC=${PROJROOT}/src
PROJLIB=${PROJROOT}/lib
PROJEXTRA=${PROJROOT}/extra

echo "- PROJSRC IS ${PROJSRC}"

if [[ -d ${PROJSRC} ]]; then

  if [[ -z "${TEMPLATE}" ]]; then
    TEMPLATE=default
  fi

  TEMPLATEROOT=${TOOLROOT}/templates
  CURRENTTEMPLATE="${TEMPLATEROOT}/${BUILDTYPE}/${TEMPLATE}"

  echo "- Using Template ${TEMPLATE}"

  #####
  TARGFILE="${BUILDDIR}/${BUILDTYPE}.js"
  CONTFILE=$TARGFILE

  echo "-----------------"
  echo "Phase 1/4: Aggregate and create ${BUILDTYPE}${BUILDFLAV} Closure"
  cp "${TOOLROOT}/build/make-src/${BUILDTYPE}${BUILDFLAV}-closure.in.jst" "${TARGFILE}" || exit 100

  #if [[ -n $BUILDENC ]]; then
  #  CONTFILE="${BUILDDIR}/${BUILDTYPE}.enc.js"
  #  touch $CONTFILE
  #fi

  cat "${TOOLROOT}/build/make-src/template${BUILDFLAV}.js" >>"${CONTFILE}" || exit 100

  if [[ -f ${PROJSRC}/main.js.in ]]; then
    echo "- Using custom In closure"
    cat "${PROJSRC}/main.js.in" >>"${CONTFILE}"
  else
    echo "- No custom In closure in ${PROJSRC}/main.js.in"
  fi

  i="0"

  aggregate "${CURRENTTEMPLATE}/src" "${CONTFILE}"
  aggregate "${PROJLIB}" "${CONTFILE}"
  aggregate "${PROJSRC}" "${CONTFILE}"

  if [[ -f ${PROJSRC}/main.js ]]; then
    echo "- Using Custom Application Entry Point"
    MAINFILE=${PROJSRC}/main.js
  elif [[ -f ${CURRENTTEMPLATE}/src/main.js ]]; then
    echo "- Using Template Application Entry Point"
    MAINFILE=${CURRENTTEMPLATE}/src/main.js
  else
    echo "! No Entry Point, please create main.js in ${PROJSRC} if needed"
  fi

  if [[ -n "${MAINFILE}" ]]; then
    cat "${MAINFILE}" >>"${CONTFILE}"
  fi

  if [[ -f ${PROJSRC}/main.js.out ]]; then
    echo "- Using custom out closure"
    cat "${PROJSRC}/main.js.out" >>"${CONTFILE}"
  else
    echo "- No custom out closure in ${PROJSRC}/main.js.out"
  fi

  #if [[ -n $BUILDENC ]]; then
  #  RESULT=$(${TOOLROOT}/build/make-src/encodebase.js ${CONTFILE})
  #  echo "//////////////////////// ${CONTFILE} " >>"${TARGFILE}"
  #  echo "eval (atob(\"${RESULT}\"));" >>"${TARGFILE}"
  #  echo "/////" >>"${TARGFILE}"
  #fi

  cat "${TOOLROOT}/build/make-src/${BUILDTYPE}${BUILDFLAV}-closure.out.jst" >>"${TARGFILE}"

  cp "${BUILDDIR}/${BUILDTYPE}.js" "${BUILDDIR}/${BUILDTYPE}.rx.js"

  if [[ ! -f "${BUILDDIR}/${BUILDTYPE}.rx.js" ]]; then
    echo "! failed to create ${BUILDDIR}/${BUILDTYPE}.rx.js"
    exit 99
  fi

  echo "-----------------"
  echo "Phase 2/4: Obfuscate module names"

  i="0"
  asig=""
  valu=""
  valumd5=""

  if [[ -d "${CURRENTTEMPLATE}/src" ]]; then
    obfuscateModules "${CURRENTTEMPLATE}/src"
  fi

  if [[ -d "${PROJLIB}" ]]; then
    obfuscateModules "${PROJLIB}"
  fi

  if [[ -d "${PROJSRC}" ]]; then
    obfuscateModules "${PROJSRC}"
  fi

  echo "${BUILDOUTVAR}(function (${asig}XX) {" >"${BUILDDIR}/${BUILDTYPE}.ox.js"
  cat "${BUILDDIR}/${BUILDTYPE}.rx.js" >>"${BUILDDIR}/${BUILDTYPE}.ox.js"
  echo "})(${valumd5}0)" >>"${BUILDDIR}/${BUILDTYPE}.ox.js"

  # need to turn off uselessCode as it complains when re-minifying mithril.js
  npx google-closure-compiler ${CCMODE} --jscomp_off uselessCode --jscomp_off suspiciousCode --js="${BUILDDIR}/${BUILDTYPE}.ox.js" --js_output_file="${BUILDDIR}/${BUILDTYPE}.min.js"

  if [[ -f ${PROJEXTRA}/libs.txt ]]; then
    "${TOOLROOT}/scripts/crunch.sh" "${PROJEXTRA}/libs.txt" ${TEMPDEST}/${BUILDTYPE}.js
  else
    touch ${TEMPDEST}/${BUILDTYPE}.js
  fi

  if [[ -n "${BUILD_DEBUG}" ]]; then
    cp "${TEMPDEST}/${BUILDTYPE}.js" "${TEMPDEST}/${BUILDTYPE}.debug.js"
    cat "${BUILDDIR}/${BUILDTYPE}.ox.js" >> "${TEMPDEST}/${BUILDTYPE}.debug.js"
  fi

  cat "${BUILDDIR}/${BUILDTYPE}.min.js" >>"${TEMPDEST}/${BUILDTYPE}.js"

else
  echo "! No source files found in ${PROJSRC}"
fi

echo "-----------------"
echo "Phase 3/4: Compile  ${BUILDTYPE} ${NAME} Styles"

# copy extra styles

if [[ -f ${PROJEXTRA}/css.txt ]]; then
  "${TOOLROOT}/scripts/crunch.sh" "${PROJEXTRA}/css.txt" "${BUILDDIR}/${BUILDTYPE}.css"
fi

# copy template styles

aggregateStyle "${CURRENTTEMPLATE}/css/**"

# copy main module styles
aggregateStyle "${PROJROOT}/css"
aggregateStyle "${PROJROOT}/css/**"

# copy section styles
aggregateStyle "${PROJSRC}/**/css"

# cp "${BUILDDIR}/${BUILDTYPE}.css"  "${TEMPDEST}/${BUILDTYPE}.css"

if [[ -f "${BUILDDIR}/${BUILDTYPE}.css" ]]; then

  if [[ -n ${BUILD_SKIPMINIFYCSS} ]]; then
    echo "! Not Minifying styles"
    cp "${BUILDDIR}/${BUILDTYPE}.css" "${TEMPDEST}/${BUILDTYPE}.css"
  else
    echo "- Minifying styles"
    echo "${NODEMODULES}/.bin/uglifycss" "${BUILDDIR}/${BUILDTYPE}.css"
    "${NODEMODULES}/.bin/uglifycss" "${BUILDDIR}/${BUILDTYPE}.css" >"${TEMPDEST}/${BUILDTYPE}.css"
  fi

fi

echo "-----------------"
echo "Phase 4/4: Copying ${BUILDTYPE} ${NAME} Assets"

if [[ -d "${CURRENTTEMPLATE}/assets" ]]; then
  cp -r ${CURRENTTEMPLATE}/assets/* "${TEMPDEST}/" || echo "- Template ${TEMPLATE} does not provide Assets" && echo "- Including ${TEMPLATE} assets"
else
  echo "- ${TEMPLATE} does not provide Assets"
fi

if [[ -d "${PROJROOT}/assets" ]]; then
  cp -r ${PROJROOT}/assets/* "${TEMPDEST}/" 2>/dev/null || echo "- ${BUILDTYPE} ${NAME} does not provide additional assets"
else
  echo "- ${BUILDTYPE} ${NAME} does not provide additional assets"
fi

echo "-----------------"
echo "${BUILDTYPE} ${NAME}: Build Finished."
echo "✅  Generated files in ${TEMPDEST}"

if [[ -d ${BUILDDIR} && -z ${KEEP} ]]; then
  rm -rf "${BUILDDIR}"
fi
