#!/usr/bin/env bash
# Copyright (c) 2022 DisplayLink (UK) Ltd.

set -eu

if [[ ! $# -eq 2 ]]; then
  echo "Usage: ${BASH_SOURCE[0]##*/} <arch> <debian_revision>"
  exit 1
fi

readonly evdi_arch=${1:?}
readonly debian_revision=${2:?}

export_CC_flag_with_proper_compiler()
{
  [[ ${CC+x} ]] && return

  case $evdi_arch in
  amd64)
  export CC=gcc
  ;;
  armhf)
  export CC=arm-linux-gnueabihf-gcc
  ;;
  arm64)
  export CC=aarch64-linux-gnu-gcc
  ;;
  esac
}

build_libevdi()
{
  (
    export_CC_flag_with_proper_compiler
    make -C library clean default
  )
}

create_evdi_deb_package()
{
  local temp_dir
  temp_dir=$(mktemp -d)

  local repo_dir="$1"
  local deb_dir="$temp_dir/EVDI"
  local control_dir="$deb_dir/DEBIAN"
  local docs_dir="$deb_dir/usr/share/doc/$evdi_package_name"

  mkdir -p \
      "$control_dir" \
      "$deb_dir/usr/src" \
      "$deb_dir/var/log/displaylink" \
      "$docs_dir" \
      "$deb_dir"/etc/{modules-load,modprobe}.d

  (
    cd "$repo_dir"

    git archive --format tar HEAD module | (cd "$temp_dir" && tar xf -)

    if ! mv "$temp_dir/module" "$deb_dir/usr/src/evdi-$evdi_version"; then
      echo >&2 "Failed to move evdi module sources"
      rm -rf "$temp_dir"
      return 1
    fi

    if ! build_libevdi; then
      echo >&2 "Failed to build evdi library"
      rm -rf "$temp_dir"
      return 1
    fi

    if ! install -Dm 644 library/libevdi.so "$deb_dir/usr/lib/libevdi.so.$evdi_version"; then
      echo >&2 "Failed to copy evdi library"
      rm -rf "$temp_dir"
      return 1
    else
    (
      local major_version=${evdi_version%%.*}
      cd "$deb_dir/usr/lib/"
      ln -s "libevdi.so.$evdi_version" \
           "libevdi.so"
      ln -s "libevdi.so.$evdi_version" \
          "libevdi.so.$major_version"
    )
    fi
    if ! install -m 644 library/LICENSE "$docs_dir/copyright"; then
      echo >&2 "Failed to copy library LICENSE"
      rm -rf "$temp_dir"
      return 1
    fi
  )

  cat > "$control_dir/control" << EOF
Package: evdi
Version: $evdi_version-$debian_revision
Maintainer: $evdi_maintainer
Source: evdi
Section: kernel
Depends: mokutil, dkms, libdrm-dev, libc6-dev
Conflicts: libevdi0, libevdi0-dev, evdi-dkms
Architecture: $evdi_arch
Priority: optional
Description: $evdi_description
EOF

  cat > "$control_dir/preinst" << EOF
#!/bin/bash

if [[ -e /opt/displaylink/evdi.tar.gz ]]
then
  echo >&2 "Error: Another EVDI distribution detected"
  exit 1
fi
EOF

  cat > "$control_dir/postinst" << EOF
#!/bin/bash

set -e

function notify-send2()
{
  local user uid program_path

  user=\$(logname) \
    && [[ \$user ]] \
    && uid=\$(id -u "\$user") \
    && program_path=\$(command -v notify-send) \
    && sudo -u "\$user" "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\$uid/bus" "\$program_path" "\$@" \
    || return 0
}

build_evdi()
{
  local evdi_dir='/usr/src/evdi-$evdi_version'
  local dkms_evdi_path='/var/lib/dkms/evdi'
  local make_log_regex="\$dkms_evdi_path/[[:alnum:]./]+/make\\\\.log"

  local evdi_make_log_path
  evdi_make_log_path="/var/log/displaylink/evdi_install_make.\$(date '+%F-%H%M').log"

  dkms install "\$evdi_dir"
  local retval=\$?
  if mokutil --sb-state | grep -Fi "SecureBoot enabled" > /dev/null; then
    if ! update-secureboot-policy --enroll-key 2> /dev/null; then
      echo >&2 "Failed to enroll SecureBoot key."
    fi
  fi

  local dkms_log_path
  dkms_log_path=\$(find "/var/lib/dkms/evdi/${evdi_version}" -name make.log)
  cp "\${dkms_log_path}" "\${evdi_make_log_path}"

  if [[ \$retval == 3 ]]; then
    echo >&2 "EVDI DKMS module already installed."
  elif [[ \$retval != 0 ]]; then
    echo >&2 "Failed to install evdi to the kernel tree."
    dkms remove 'evdi/$evdi_version' --all
    exit 1
  fi
}

add_mod_options()
{
  local module_file='/etc/modules-load.d/evdi.conf'
  echo 'evdi' > "\$module_file"

  local conf_file='/etc/modprobe.d/evdi.conf'
  [[ -f \$conf_file ]] && return

  echo "options evdi initial_device_count=4" > "\$conf_file"

  local drm_deps
  drm_deps=\$(sed -n '/^drm_kms_helper/p' /proc/modules | awk '{print \$4}' | tr ',' ' ')
  drm_deps=\${drm_deps/evdi/}
  [[ -z \$drm_deps ]] && return 0

  echo "softdep evdi pre: \$drm_deps" >> "\$conf_file"
}

build_evdi
add_mod_options
notify-send2 -a "DisplayLinkManager" "Reboot required" \
        "DisplayLink evdi module installed successfully. Reboot your computer to ensure proper functioning of the software."

printf "\n\n%s\n%s\n%s\n\n\n" "Reboot required" "DisplayLink evdi module installed successfully." \
        "Please reboot your computer to ensure the proper functioning of the software."
EOF

  cat > "$control_dir/prerm" << EOF
#!/bin/bash

set -e

dkms remove 'evdi/$evdi_version' --all
rm -f /etc/{modprobe,modules-load}.d/evdi.conf
EOF

  cat > "$control_dir/postrm" << 'EOF'
#!/bin/bash

set -e

if [[ $1 == purge ]]; then
  rm -rf /var/log/displaylink
fi
EOF

  chmod 0755 "$control_dir"/{pre,post}{rm,inst}

  (
    cd "$temp_dir"
    fakeroot dpkg-deb --build EVDI
  )

  mv "$temp_dir/EVDI.deb" "evdi-${evdi_version}-${debian_revision}_${evdi_arch}.deb"

  rm -rf "$temp_dir"
}

script_dir="$(dirname "${BASH_SOURCE[0]}")"

evdi_package_name=
evdi_version=
evdi_description=
evdi_maintainer=
# shellcheck disable=SC1090
. "$script_dir/deb_config" || exit 1


: "${evdi_maintainer:?}" "${evdi_description:?}" "${evdi_version:?}"

create_evdi_deb_package "$script_dir/.."

