#!/bin/bash

# Uncomment next line to debug
# set -x

function message() {
  echo "$*" 2>&1 | tee --append "${CURRENT_LOG}"
}

function newLine() {
  echo 2>&1 | tee --append "${CURRENT_LOG}"
}

function title() {
  message "# $*"
  newLine
  # output to summary log
  echo "## $(date +"%T") $*" >> "${SUMMARY_LOG}"
  echo >> "${SUMMARY_LOG}"
}

function section() {
  # output to current log
  newLine
  message "## $*"
  newLine
  # output to summary log
  echo "- $(date +"%T") $*" >> "${SUMMARY_LOG}"
}

function code() {
  newLine
  echo "\`\`\`bash" 2>&1 | tee --append "${CURRENT_LOG}"
  echo "$*" 2>&1 | tee --append "${CURRENT_LOG}"
  echo "\`\`\`" 2>&1 | tee --append "${CURRENT_LOG}"
  newLine
}

function listItem() {
  message "- $*"
}

function execCommand() {
  result=$($* 2>&1)
  trimmedResult=$(echo -- $result)
  if [ -z "$trimmedResult" ]; then
    listItem "command \"$*\" outputs"
    code "${result}"
  else
    listItem "command \"$*\" executed with no outputs"
  fi
}









# cleanup apt state
function cleanup-apt-pre() {
  listItem apt update
  sudo apt-get -qq update > /dev/null
  listItem apt clean
  sudo apt-get -qq clean > /dev/null
  listItem apt upgrade
  sudo apt-get -qq --assume-yes upgrade 2>&1 | tee --append "${CURRENT_LOG}" | grep --line-buffered -e "^Get" -e "Setting up"
  listItem apt update
  sudo apt-get -qq update 2>&1 | tee --append "${CURRENT_LOG}" | grep --line-buffered -e "^Get" -e "Setting up" 
  listItem apt fix broken
  sudo apt-get -qq --fix-broken install > /dev/null
}

function cleanup-apt-post() {
  listItem apt autoremove
  sudo apt-get -qq --assume-yes autoremove > /dev/null
  listItem apt clean
  sudo apt-get -qq clean > /dev/null
}


# define log filenames
CHECK_LOG=$(pwd)/${PROJECT_LOG_DIR}/check-environment.md
PACKAGE_LOG=$(pwd)/${PROJECT_LOG_DIR}/prepare-package-environment.md
BUILD_PACKAGE_LOG=$(pwd)/${PROJECT_LOG_DIR}/build-package.md
SUMMARY_LOG=$(pwd)/${PROJECT_LOG_DIR}/summary.md
LOG_DIR=$(dirname "${BUILD_PACKAGE_LOG}")

# pipeline initialization

if [[ "$OS" == "win10" || "$OS" == "win11" ]]; then
    # there is no docker on windows
    CONTAINER_ID=0
else
    CONTAINER_ID=$(cat /proc/self/cgroup | head -n 1 | cut -d '/' -f3)
fi

# default stage is coverage
if [[ "$CAMITK_CI_STAGE" == "" ]]; then
    CAMITK_CI_STAGE="$STAGE_PACKAGE";
fi

# default mode is Continuous for develop, Experimental for any other branches
if [[ "$CAMITK_CI_MODE" == "" ]]; then
    if [[ "$CI_COMMIT_REF_NAME" == "develop" ]]; then
        CAMITK_CI_MODE="Continuous";
    else
        CAMITK_CI_MODE="Experimental";
    fi
fi

# cleanup log directory
if [ -d "${PROJECT_LOG_DIR}" ] ; then
    rm -rf "${PROJECT_LOG_DIR}"
fi
mkdir -p "${PROJECT_LOG_DIR}"

# prepare Summary
export CURRENT_LOG=${SUMMARY_LOG}
title Summary log started $(date)

# check log
export CURRENT_LOG=${CHECK_LOG}
title Check log

DEBIAN_VERSION=$(cat /proc/version)
ARTIFACT_URL="https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/jobs/$CI_JOB_ID/artifacts/raw/packaging-debian-unstable-develop/log"
export EMAIL="Emmanuel.Promayon@univ-grenoble-alpes.fr"
# git config --local user.email Emmanuel.Promayon@univ-grenoble-alpes.fr
# git config --local user.name "Emmanuel Promayon"

# output all information to report file
message "Docker container id....... $CONTAINER_ID"
message "Job....................... $CI_JOB_NAME"
message "Job id.................... $CI_JOB_ID"
message "Build Directory........... $PROJECT_BUILD_DIR"
message "Log Directory............. $PROJECT_LOG_DIR"
message "Log Directory (full)...... $LOG_DIR"
message "Branch.................... $CI_COMMIT_REF_NAME"
message "CAMITK_CI_MODE............ $CAMITK_CI_MODE"
message "CAMITK_CI_STAGE........... $CAMITK_CI_STAGE"
message "Debian version............ $DEBIAN_VERSION"
message "Artifact URL.............. $ARTIFACT_URL"

export CURRENT_LOG=${PACKAGE_LOG}
title Package log

section Prepare image
listItem id=$(id)
listItem Working Directory=$(pwd)
message

section Cleanup apt preprocess
# DEBIAN_FRONTEND=noninteractive is to prevent question asked on interactive shell (e.g. "Please select the layout matching the keyboard for this machine"
export DEBIAN_FRONTEND=noninteractive
cleanup-apt-pre

section Setting apt source

listItem Modifying /etc/apt/sources.list
sudo apt-get -qq --assume-yes install netselect-apt 2>&1 | tee --append ${CURRENT_LOG} | grep --line-buffered -e "^Get" -e "^Setting up" 
sudo netselect-apt -c france -t 15 -a amd64 -n sid

listItem apt install wget git-buildpackage lintian autopkgtest cme
sudo apt-get -qq --assume-yes install wget git-buildpackage lintian autopkgtest cme 2>&1 | tee --append ${CURRENT_LOG} | grep --line-buffered -e "^Get" -e "^Setting up"

section Clean apt postprocess
cleanup-apt-post

section Setup gbp user configuration
listItem Creating ~/.gbp.conf
cat > ~/.gbp.conf << 'EOF'
[DEFAULT]
# Add a very verbose lintian after the build and normal lintian check
postbuild = ~/.gbp-postbuild.sh
# display information
prebuild = echo "=========================" && echo "GBP_GIT_DIR=$GBP_GIT_DIR" && echo "GBP_BUILD_DIR=$GBP_BUILD_DIR" && echo "========================="
EOF

listItem Creating ~/.gbp-postbuild.sh
cat > ~/.gbp-postbuild.sh << 'EOF'
#!/bin/bash
# works when gbp exports for instance, the following variables
# - GBP_BUILD_DIR the directory containing the source and debian/ subdirectory
# - GBP_CHANGES_FILE the change file camitk_x.y.z-v_amd64.changes (in the directory above GBP_BUILD_DIR)

set -e

# ---------------------- variables ----------------------
echo "========================="
echo "GBP_BUILD_DIR=$GBP_BUILD_DIR"
echo "GBP_CHANGES_FILE=$GBP_CHANGES_FILE"
echo "Changes files:"
ls -la $GBP_CHANGES_FILE
export LOG_DIR=$GBP_BUILD_DIR/..
echo "Files in log dir $LOG_DIR:"
ls -la $LOG_DIR

# ---------------------- lintian ----------------------
echo "========================="
lintianHost=$(lintian --version)
lintian -iIE --pedantic $GBP_CHANGES_FILE > >(tee $LOG_DIR/lintian.log) 2>&1

# ---------------------- autopkgtest ----------------------
echo "========================="
# we need to write a bash script in order to run autopkgtest inside the sid-dev docker
#sudo autopkgtest -l $LOG_DIR/autopkgtest.log $GBP_CHANGES_FILE -- null
cd $LOG_DIR
autopkgtest -l autopkgtest.log $GBP_CHANGES_FILE --setup-commands="apt-get update" -- podman debian:sid
EOF

listItem Make ~/.gbp-postbuild.sh executable
chmod a+x ~/.gbp-postbuild.sh

execCommand ls -la ~

section Preparing source code...
listItem Get current develop branch version
execCommand wget --quiet https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/raw/develop/CamiTKVersion.cmake --output-document=/tmp/CamiTKVersion.cmake

export VERSION_MAJOR=$(grep CAMITK_VERSION_MAJOR /tmp/CamiTKVersion.cmake | cut -f2 -d'"')
export VERSION_MINOR=$(grep CAMITK_VERSION_MINOR /tmp/CamiTKVersion.cmake | cut -f2 -d'"')
export VERSION_PATCH=$(grep CAMITK_VERSION_PATCH /tmp/CamiTKVersion.cmake | cut -f2 -d'"')
export NEW_VERSION="$VERSION_MAJOR.$VERSION_MINOR.$(date +"%Y%m%d%H%M")"
section → Detected version: $NEW_VERSION

# copy the clone to another workspace to work on
listItem Clone debian git into camitk-debian
rm -rf camitk-debian
execCommand gbp clone https://salsa.debian.org/med-team/camitk.git camitk-debian
cd camitk-debian

listItem Setup git config
git config --local user.email Emmanuel.Promayon@univ-grenoble-alpes.fr
git config --local user.name "Emmanuel Promayon"
execCommand git status

section Download the current develop version tarball
rm -f ../*.tar.bz2
execCommand gbp import-orig \
    --upstream-branch=upstream \
    --debian-branch=master \
    --no-pristine-tar \
    --no-interactive \
    --upstream-version=$NEW_VERSION \
    https://gricad-gitlab.univ-grenoble-alpes.fr/CamiTK/CamiTK/-/archive/develop/CamiTK-develop.tar.bz2

section Add a snapshot in history
execCommand gbp dch --git-author --upstream-branch=upstream --debian-branch=master --new-version=$NEW_VERSION-1
listItem debian/changelog last entry
result=$(sed -n "1,/^ --/ p" debian/changelog 2>&1)
code "${result}"




section Install deps
cd ..
cleanup-apt-pre
result=$(mk-build-deps -t "apt-get --assume-yes --no-install-recommends -o Debug::pkgProblemResolver=yes" --install "camitk-debian/debian/control" 2>&1)
code "${result}"
cleanup-apt-post

export CURRENT_LOG=${BUILD_PACKAGE_LOG}
title Build package log
cd camitk-debian

section Try to build the package using gbp
{ time gbp buildpackage \
           --git-no-create-orig \
           --git-ignore-new \
           --git-postbuild='~/.gbp-postbuild.sh' 2>&1 ; } 2>&1 | tee --append ${CURRENT_LOG} | grep --line-buffered -e "^dpkg" -e "Built target" -e "Test \#" -e "^W:" -e "^P:" -e "^E:" -e "^I:" -e "^X:" -e "^=====" -e "^cepgenerator-test.sh" -e "^config-test.sh" -e "CMake.*Warning"

section Checking debian files...
git checkout master
execCommand DEBIAN_FRONTEND=noninteractive cme check dpkg
execCommand DEBIAN_FRONTEND=noninteractive cme check dpkg-control
execCommand DEBIAN_FRONTEND=noninteractive cme check dpkg-copyright

section Checking current version of debian-policy
sudo apt-get update
execCommand sudo apt-cache policy debian-policy
DEB_POLICY_CURRENT=$(sudo apt-cache policy debian-policy | grep "^     [0-9]" | sed -e "s/ [0-9]*$//g" | sed -e "s/\.[0.9]$//g" | xargs)
DEB_POLICY_IN_USE=$(grep "Standards-Version" debian/control | cut -f2 -d" " | xargs)
message Debian policy version: current=$DEB_POLICY_CURRENT used=$DEB_POLICY_IN_USE
if [[ "$DEB_POLICY_CURRENT" =~ "$DEB_POLICY_IN_USE" ]]; then
    message → Debian standards version OK
else
    message → Please modify debian/control and update 'Standards-Version' field to $DEB_POLICY_CURRENT instead of $DEB_POLICY_IN_USE
    execCommand sudo apt-cache policy debian-policy
fi

section Checking current version of debhelper
sudo apt-get update
execCommand sudo apt-cache policy debhelper
DEBHELPER_CURRENT_FULL=$(sudo apt-cache policy debhelper | grep "Installed:" | cut -c14- | xargs)
DEBHELPER_CURRENT=$(echo $DEBHELPER_CURRENT_FULL | cut -f1 -d. | xargs)
DEBHELPER_IN_USE=$(grep debhelper debian/control | sed "s/.*(= \([0-9.]*\)).*/\1/" | xargs)
message Debian debhelper version: current=$DEBHELPER_CURRENT, full version is $DEBHELPER_CURRENT_FULL, used=$DEBHELPER_IN_USE
if [ "$DEBHELPER_CURRENT" == "$DEBHELPER_IN_USE" ]; then
    message → Debian debhelper version OK!
else
    message → Please update 'debhelper-compat' in debian/control to $DEBHELPER_CURRENT instead of $DEBHELPER_IN_USE
fi

section Checking package directory
execCommand ls -la .
execCommand ls -la ..
execCommand ls -la ${LOG_DIR}
execCommand ls -la camitk-build
execCommand ls -la camitk-build/lib
message share object .so file version $VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH
execCommand ls -la camitk-build/lib/x86_64-linux-gnu

section Checking overrides
LIB_FILENAME=$(ls camitk-build/lib/x86_64-linux-gnu/libcamitkcore.so.$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH)
listItem checking overrides for libcamitkcore.so in file $LIB_FILENAME with with objdump 
objdump -p $LIB_FILENAME 2>&1 | sed -n -e's/^[[:space:]]*SONAME[[:space:]]*//p' | sed -r -e's/([0-9])\.so\./\1-/; s/\.so(\.|$)//; y/_/-/; s/(.*)/\L&/' | tee --append ${CURRENT_LOG}
LIB_FILENAME=$(ls camitk-build/lib/x86_64-linux-gnu/libmonitoring.so.$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH)
listItem check overrides for libmonitoring.so in file $LIB_FILENAME with with objdump
objdump -p $LIB_FILENAME 2>&1 | sed -n -e's/^[[:space:]]*SONAME[[:space:]]*//p' | sed -r -e's/([0-9])\.so\./\1-/; s/\.so(\.|$)//; y/_/-/; s/(.*)/\L&/' | tee --append ${CURRENT_LOG}


export CURRENT_LOG=${SUMMARY_LOG}
message
message "**Checking for failure of the packaging process**"
message

if [ -f ../camitk_$NEW_VERSION-1_amd64.changes ]; then
  message Everything is OK, packages were build!
  message Summary log finished at $(date "+%T")
else
  message
  message 'changes' file not found in $(pwd)/..
  message The package was not generated, please check the artifacts and fix the problem:
  message - summary: $ARTIFACT_URL/summary.log
  message - check environment: $ARTIFACT_URL/check-environment.log
  message - prepare package environment: $ARTIFACT_URL/prepare-package-environment.log
  message - build package: $ARTIFACT_URL/build-package.log
  message 
  message To update the debian files:
  message gbp clone https://salsa.debian.org/med-team/camitk.git camitk-debian
  message cd camitk-debian
  message git config --local user.email Emmanuel.Promayon@univ-grenoble-alpes.fr
  message git config --local user.name \"Emmanuel Promayon\"
  message git checkout --track origin/master
  message git status
  message And then, for instance to fix standards version:
  message cme fix dpkg
  message 
  message Packaging failed
  message Summary log finished at $(date "+%T")
  exit 1
fi

 
