#!/bin/bash

if [ -f .compilation-options ]; then
  source ./.compilation-options
fi

echo "$ARCH"

while getopts "ksfa:" o; do
    case "${o}" in
        a) ARCH="$OPTARG";;
        k) KEEP=true;;
        s) SKIPCHECK=true;;
        f) FORCE=true;;
        *) exit 1;;
    esac
done

PACKAGE="${@:$OPTIND:1}"

DIR="$PWD"
if [ -z "$ARCH" ]; then
  ARCH=$(uname -m)
fi

if ! [ -f "$PACKAGE" ]; then
  echo "$PACKAGE is not a path to a file"
  exit 1
fi
if ! file "$PACKAGE" | grep -q 'gzip compressed data'; then
  echo "$PACKAGE is not a BPM package"
  exit 1
fi
if ! tar -tf "$PACKAGE" | grep -q 'source.sh'; then
  echo "$PACKAGE is not a BPM source package"
  exit 1
fi
echo "$Converting $PACKAGE..."

declare -A PKGINFO
# Declare and run Read Package Information function
function ReadPkgInfo() {
  local BACK="$PWD"
  cd "$DIR"
  if [ $# -eq 0 ]; then
    FILE=pkg.info
    PKGINFO_FILE=$(tar -xf "$PACKAGE" pkg.info -O)
  else
    FILE=pkg.info."$1"
  fi
  
  if ! tar -tf "$PACKAGE" "$FILE"; then
    echo "Could not find $FILE in $PACKAGE"
    exit 1
  fi
  PKGINFO_FILE=$(tar -xf "$PACKAGE" "$FILE" -O)
  
  while read line; do
    PKGINFO[$(echo -n "$line" | cut -d":" -f1 | xargs)]=$(echo -n "$line" | cut -d":" -f2 | xargs)
  done < <(tar -xf "$PACKAGE" "$FILE" -O)
  cd "$BACK"
}
ReadPkgInfo

if [ -z "$FORCE" ] && command -v bpm &> /dev/null && [ -n "$PKGINFO[depends]" ]; then
  MISSING=()
  for depend in $(echo "${PKGINFO[depends]}" | tr -d '[]' | tr ',' '\n' ); do
    if ! bpm info "$depend" &> /dev/null; then
      MISSING+=("$depend")
    fi
  done
  if [ "${#MISSING[@]}" -ne 0 ]; then
    echo "The following dependencies could not be resolved: ${MISSING[@]}"
    EXIT=true
  fi
elif ! command -v bpm &> /dev/null; then
  echo "BPM not in PATH. Skipping dependency resolution"
elif [ -n "$FORCE" ]; then
  echo "Force compilation enabled. Skipping dependency resolution"
fi

if [ -z "$FORCE" ] && command -v bpm &> /dev/null && [ -n "$PKGINFO[make_depends]" ]; then
  MISSING=()
  for depend in $(echo "${PKGINFO[make_depends]}" | tr -d '[]' | tr ',' '\n' ); do
    if ! bpm info "$depend" &> /dev/null; then
      MISSING+=("$depend")
    fi
  done
  if [ "${#MISSING[@]}" -ne 0 ]; then
    echo "The following make dependencies could not be resolved: ${MISSING[@]}"
    EXIT=true
  fi
elif ! command -v bpm &> /dev/null; then
  echo "BPM not in PATH. Skipping make dependency resolution"
elif [ -n "$FORCE" ]; then
  echo "Force compilation enabled. Skipping make dependency resolution"
fi

if [ -n "$EXIT" ]; then
  exit 1
fi

# Creating temporary compilation directory structure
TEMPDIR="/var/tmp/bpm_source_${PKGINFO[name]}"
if [ -d "$TEMPDIR" ] && [ -z "$KEEP" ]; then
  rm -rf "$TEMPDIR"
fi
mkdir -p "$TEMPDIR"
mkdir -p "$TEMPDIR"/source
[ -d "$TEMPDIR"/output ] && rm -rf "$TEMPDIR"/output
mkdir -p "$TEMPDIR"/output
tar -xf "$PACKAGE" -C "$TEMPDIR" source.sh
if tar -xf "$PACKAGE" -C "$TEMPDIR" source-files &> /dev/null; then
  mv "$TEMPDIR"/source-files/* "$TEMPDIR"/
  rm -d "$TEMPDIR"/source-files
fi
PACKAGE_SCRIPTS=()
while read line; do
  PACKAGE_SCRIPTS+=("$line")
done < <(tar -tf "$PACKAGE" | grep -v -E 'source.sh|pkg.info|source-files')
tar -xf "$PACKAGE" -C "$TEMPDIR" ${PACKAGE_SCRIPTS[@]} &> /dev/null
cd "$TEMPDIR"

# Declare and run Set Variables function
function SetVariables() {
  export BPM_PKG_NAME="${PKGINFO[name]}"
  export BPM_PKG_DESC="${PKGINFO[description]}"
  export BPM_PKG_VERSION="${PKGINFO[version]}"
  export BPM_PKG_URL="${PKGINFO[url]}"
  export BPM_PKG_ARCH="${PKGINFO[architecture]}"
  IFS=',' read -r -a BPM_PKG_DEPENDS <<< "${PKGINFO[depends]}"
  IFS=',' read -r -a BPM_PKG_MAKE_DEPENDS <<< "${PKGINFO[make_depends]}"
  export BPM_PKG_DEPENDS
  export BPM_PKG_MAKE_DEPENDS
  export BPM_WORKDIR="$TEMPDIR"
  export BPM_SOURCE="$TEMPDIR"/source
  export BPM_OUTPUT="$TEMPDIR"/output
}
SetVariables

# Declare Run Package Function function
function RunPkgFunction() {
  if [ $# -eq 0 ]; then
    echo "No function name given"
    exit 1
  fi
  func="$1"

  if [[ $(type -t "$func") == function ]]; then
    echo "Running ${func}() function..."
    bash -e -c "$func"
    if [ $? -ne 0 ]; then
      echo "Failed to run ${func}() function in source.sh"
      exit 1
    fi
  fi
}

# Read source.sh file and source functions
set -a
source source.sh
set +a

cd "$BPM_WORKDIR"
RunPkgFunction prepare

cd "$BPM_SOURCE"
RunPkgFunction build

cd "$BPM_SOURCE"
if [ -z "$SKIPCHECK" ]; then
  RunPkgFunction check
fi

# Packaging all packages
for func in $(typeset -F | awk '{print $3}' | grep '^package'); do
  cd "$BPM_SOURCE"
  if [[ "$func" == "package" ]]; then
    pkgname="$BPM_PKG_NAME"
    ReadPkgInfo
  else
    pkgname="${func##package-}"
    ReadPkgInfo "$pkgname"
  fi
  SetVariables
  echo "Running ${func}() function..."
  touch  "$TEMPDIR"/fakeroot_file_"$pkgname"
  fakeroot -s "$TEMPDIR"/fakeroot_file_"$pkgname" bash -e -c "$func"
  if [ $? -ne 0 ]; then
    echo "Failed to run ${func}() function in source.sh"
    exit 1
  fi
  cd "$BPM_WORKDIR"
  touch pkg.info
  if [[ "$pkgname" == "$BPM_PKG_NAME" ]]; then
    echo "${PKGINFO_FILE}" > pkg.info
  else
    echo "${PKGINFO_FILE}" > pkg.info
  fi
  echo "${PKGINFO_FILE}" > pkg.info
  sed -i "s/architecture:.*/architecture: ${ARCH}/g" pkg.info
  sed -i 's/type:.*/type: binary/g' pkg.info
  fakeroot -i "$TEMPDIR"/fakeroot_file_"$pkgname" tar -czpf "$pkgname".tar.gz pkg.info ${PACKAGE_SCRIPTS[@]} output --transform 's/output/files/'
  mv "$pkgname".tar.gz "$DIR"/"$pkgname"-"$BPM_PKG_VERSION"-"$ARCH".bpm
  echo "Packaged ${pkgname} successfully!"
  rm "$TEMPDIR"/fakeroot_file_"$pkgname"
  rm -r output/
  mkdir output
  rm pkg.info
done

if [ -z "$KEEP" ]; then
  rm -rf "$TEMPDIR"
fi
