#!/usr/bin/env bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

set -exu

if [ $# -lt 2 ]; then
  echo "Usage: $0 VERSION rc"
  echo "       $0 VERSION release"
  echo "       $0 VERSION local"
  echo " e.g.: $0 0.13.0 rc                # Verify 0.13.0 RC"
  echo " e.g.: $0 0.13.0 release           # Verify 0.13.0"
  echo " e.g.: $0 0.13.0-dev20210203 local # Verify 0.13.0-dev20210203 on local"
  exit 1
fi

VERSION="$1"
TYPE="$2"

SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TOP_SOURCE_DIR="${SOURCE_DIR}/../.."
local_prefix="${TOP_SOURCE_DIR}/dev/tasks/linux-packages"

artifactory_base_url="https://packages.apache.org/artifactory/arrow"

distribution=$(. /etc/os-release && echo "${ID}")
distribution_version=$(. /etc/os-release && echo "${VERSION_ID}" | grep -o "^[0-9]*")
repository_version="${distribution_version}"

cmake_package=cmake
cmake_command=cmake
gcc_toolset=
scl_package=
have_arrow_libs=no
have_flight=yes
have_gandiva=yes
have_glib=yes
have_parquet=yes
have_ruby=yes
have_vala=yes
ruby_devel_packages=(ruby-devel)
enablerepo_epel="--enablerepo=epel"
install_command="dnf install -y --enablerepo=crb"
uninstall_command="dnf remove -y"
clean_command="dnf clean"
info_command="dnf info --enablerepo=crb"

echo "::group::Prepare repository"

case "${distribution}-${distribution_version}" in
  almalinux-8)
    distribution_prefix="almalinux"
    gcc_toolset=14
    have_arrow_libs=yes
    ruby_devel_packages+=(redhat-rpm-config)
    install_command="dnf install -y --enablerepo=powertools"
    info_command="dnf info --enablerepo=powertools"
    ;;
  almalinux-9)
    distribution_prefix="almalinux"
    gcc_toolset=12
    ruby_devel_packages+=(redhat-rpm-config)
    ;;
  almalinux-*)
    distribution_prefix="almalinux"
    ruby_devel_packages+=(redhat-rpm-config)
    ;;
  amzn-*)
    distribution_prefix="amazon-linux"
    enablerepo_epel=""
    # gcc-c++ installs kernel6.12-headers as a dependency
    # automatically. But it conflicts with kernel-headers that is
    # grpc-devel dependency. If we use "--allowerasing" when we
    # install grpc-devel (via arrow-flight-devel), kernel6.12-headers
    # is replaced with kernel-headers automatically. gcc-c++ works
    # with kernel-headers too. So using kernel-headers is not a
    # problem.
    install_command="dnf install -y --allowerasing"
    info_command="dnf info"
    ;;
  centos-*)
    distribution_prefix="centos"
    repository_version+="-stream"
    ;;
esac
if [ "$(arch)" = "aarch64" ]; then
  have_gandiva=no
fi

if [ "${TYPE}" = "local" ]; then
  case "${VERSION}" in
    *-dev*)
      package_version="$(echo "${VERSION}" | sed -e 's/-dev\(.*\)$/-0.dev\1/g')"
      ;;
    *-rc*)
      package_version="$(echo "${VERSION}" | sed -e 's/-rc.*$//g')"
      package_version+="-1"
      ;;
    *)
      package_version="${VERSION}-1"
      ;;
  esac
  release_path="${local_prefix}/yum/repositories"
  case "${distribution}" in
    almalinux)
      package_version+=".el${distribution_version}"
      release_path+="/almalinux"
      ;;
    amzn)
      package_version+=".${distribution}${distribution_version}"
      release_path+="/amazon-linux"
      ;;
    centos)
      package_version+=".el${distribution_version}"
      release_path+="/centos"
      ;;
  esac
  release_path+="/${repository_version}/$(arch)/Packages"
  release_path+="/apache-arrow-release-${package_version}.noarch.rpm"
  ${install_command} "${release_path}"
else
  package_version="${VERSION}"
  if [ "${TYPE}" = "rc" ]; then
    suffix=${TYPE%-release}
    distribution_prefix+="-${suffix}"
  fi
  ${install_command} \
    ${artifactory_base_url}/${distribution_prefix}/${repository_version}/apache-arrow-release-latest.rpm
fi

if [ "${TYPE}" = "local" ]; then
  sed \
    -i"" \
    -e "s,baseurl=https://packages\.apache\.org/artifactory/arrow/,baseurl=file://${local_prefix}/yum/repositories/,g" \
    /etc/yum.repos.d/Apache-Arrow.repo
  keys="${local_prefix}/KEYS"
  if [ -f "${keys}" ]; then
    cp "${keys}" /etc/pki/rpm-gpg/RPM-GPG-KEY-Apache-Arrow
  fi
else
  if [ "${TYPE}" = "rc" ]; then
    suffix=${TYPE%-release}
    sed \
      -i"" \
      -e "s,/almalinux/,/almalinux-${suffix}/,g" \
      -e "s,/centos/,/centos-${suffix}/,g" \
      -e "s,/amazon-linux/,/amazon-linux-${suffix}/,g" \
      /etc/yum.repos.d/Apache-Arrow.repo
  fi
fi

echo "::endgroup::"


echo "::group::Test Apache Arrow C++"
mkdir -p build
${install_command} ${enablerepo_epel} arrow-devel-${package_version}
${install_command} \
  ${cmake_package} \
  git \
  libarchive \
  pkg-config
if [ -n "${gcc_toolset}" ]; then
  ${install_command} \
    gcc-toolset-${gcc_toolset} \
    make
  . /opt/rh/gcc-toolset-${gcc_toolset}/enable
else
  ${install_command} \
    gcc-c++ \
    make
fi
# cmake version 3.31.6 -> 3.31.6
cmake_version=$(${cmake_command} --version | head -n1 | sed -e 's/^cmake version //')
# 3.31.6 -> 3.31
cmake_version_major_minor=${cmake_version%.*}
# 3.31 -> 3
cmake_version_major=${cmake_version_major_minor%.*}
# 3.31 -> 31
cmake_version_minor=${cmake_version_major_minor#*.}
if [ "${cmake_version_major}" -gt "3" ] || \
   [ "${cmake_version_major}" -eq "3" -a "${cmake_version_minor}" -ge "25" ]; then
  cp -a "${TOP_SOURCE_DIR}/cpp/examples/minimal_build" build/
  pushd build/minimal_build
  cmake -S . -B build_shared
  make -C build_shared -j$(nproc)
  build_shared/arrow-example
  cmake -S . -B build_static -DARROW_LINK_SHARED=OFF
  make -C build_static -j$(nproc)
  build_static/arrow-example
  mkdir -p build_pkg_config
  c++ \
    example.cc \
    -o build_pkg_config/arrow-example \
    $(pkg-config --cflags --libs arrow) \
    -std=c++2a
  build_pkg_config/arrow-example
  popd
fi
if [ -n "${gcc_toolset}" ]; then
  dnf remove -y "gcc-toolset-${gcc_toolset}-*"
  ${install_command} gcc-c++
fi
echo "::endgroup::"

if [ "${have_glib}" = "yes" ]; then
  echo "::group::Test Apache Arrow GLib"
  export G_DEBUG=fatal-warnings

  ${install_command} ${enablerepo_epel} arrow-glib-devel-${package_version}
  ${install_command} ${enablerepo_epel} arrow-glib-doc-${package_version}

  if [ "${have_vala}" = "yes" ]; then
    ${install_command} vala
    cp -a "${TOP_SOURCE_DIR}/c_glib/example/vala" build/
    pushd build/vala
    valac --pkg arrow-glib --pkg posix build.vala
    ./build
    popd
  fi

  if [ "${have_ruby}" = "yes" ]; then
    ${install_command} "${ruby_devel_packages[@]}"
    MAKEFLAGS="-j$(nproc)" gem install gobject-introspection
    ruby -r gi -e "p GI.load('Arrow')"
  fi
  echo "::endgroup::"
fi

if [ "${have_flight}" = "yes" ]; then
  echo "::group::Test Apache Arrow Flight"
  ${install_command} ${enablerepo_epel} arrow-flight-glib-devel-${package_version}
  ${install_command} ${enablerepo_epel} arrow-flight-glib-doc-${package_version}
  if [ "${have_ruby}" = "yes" ]; then
    ruby -r gi -e "p GI.load('ArrowFlight')"
  fi
  echo "::endgroup::"

  echo "::group::Test Apache Arrow Flight SQL"
  ${install_command} ${enablerepo_epel} arrow-flight-sql-glib-devel-${package_version}
  ${install_command} ${enablerepo_epel} arrow-flight-sql-glib-doc-${package_version}
  if [ "${have_ruby}" = "yes" ]; then
    ruby -r gi -e "p GI.load('ArrowFlightSQL')"
  fi
  echo "::endgroup::"
fi

if [ "${have_gandiva}" = "yes" ]; then
  echo "::group::Test Gandiva"
  if [ "${have_glib}" = "yes" ]; then
    ${install_command} ${enablerepo_epel} gandiva-glib-devel-${package_version}
    ${install_command} ${enablerepo_epel} gandiva-glib-doc-${package_version}
    if [ "${have_ruby}" = "yes" ]; then
      ruby -r gi -e "p GI.load('Gandiva')"
    fi
  else
    ${install_command} ${enablerepo_epel} gandiva-devel-${package_version}
  fi
  echo "::endgroup::"
fi

if [ "${have_parquet}" = "yes" ]; then
  echo "::group::Test Apache Parquet"
  if [ "${have_glib}" = "yes" ]; then
    ${install_command} ${enablerepo_epel} parquet-glib-devel-${package_version}
    ${install_command} ${enablerepo_epel} parquet-glib-doc-${package_version}
    if [ "${have_ruby}" = "yes" ]; then
      ruby -r gi -e "p GI.load('Parquet')"
    fi
  else
    ${install_command} ${enablerepo_epel} parquet-devel-${package_version}
  fi
  echo "::endgroup::"
fi

echo "::group::Test coexistence with old library"
${uninstall_command} apache-arrow-release
if ${install_command} \
     ${artifactory_base_url}/${distribution_prefix}/${repository_version}/apache-arrow-release-latest.rpm; then
  ${clean_command} all
  if [ "${have_arrow_libs}" = "yes" ]; then
    ${install_command} ${enablerepo_epel} arrow-libs
  else
    major_version=$(echo ${VERSION} | grep -E -o '^[0-9]+')
    previous_major_version="$((${major_version} - 1))"
    previous_so_version="${previous_major_version}00"
    if ${info_command} ${enablerepo_epel} arrow${previous_so_version}-libs; then
      ${install_command} ${enablerepo_epel} arrow${previous_so_version}-libs
    fi
  fi
fi
echo "::endgroup::"
