#!/usr/bin/env bash

set -euo pipefail

SRC_ROOT=.
ERRCNT=0

case "$OSTYPE" in
  darwin*)
    if ! type gsed &>/dev/null || ! type ggrep &>/dev/null; then
      echo "GNU sed and grep not found! You can install via Homebrew" >&2
      echo >&2
      echo "    brew install grep gnu-sed" >&2
      exit 1
    fi

    SED=gsed
    GREP=ggrep
    ;;
  *)
    SED=sed
    GREP=grep
    ;;
esac

CARGOS=$(find "${SRC_ROOT}" -type f -name "Cargo.toml" -not -path '*/target/*')

function check_package_name() {
  local regex_to_cut_pkgname='s/^\[\(package\)\]\nname\(\|[ ]\+\)=\(\|[ ]\+\)"\(.\+\)"/\4/p'
  for cargo_toml in ${CARGOS}; do
    local pkgname=$(${SED} -n -e N -e "${regex_to_cut_pkgname}" "${cargo_toml}")
    if [ -z "${pkgname}" ]; then
      printf "Error: No package name in <%s>\n" "${cargo_toml}"
      ERRCNT=$((ERRCNT + 1))
    elif [[ "${pkgname}" =~ ^ckb- ]] || [ "${pkgname}" = "ckb" ]; then
      :
    else
      printf "Error: Package name in <%s> is not with prefix 'ckb-' (actual: '%s')\n" \
        "${cargo_toml}" "${pkgname}"
      ERRCNT=$((ERRCNT + 1))
    fi
  done
}

function check_version() {
    local regex_to_cut_version='s/^version = "\(.*\)"$/\1/p'
    local ckb_version=$(cat "${SRC_ROOT}/Cargo.toml" | tomlq -r .package.version)
    declare -A ckb_workspace_members
    members=$(tomlq -e '.workspace.members[]' Cargo.toml -r | xargs -I{} tomlq -e '.package.name' {}/Cargo.toml -r)
    for member in ${members}; do
        ckb_workspace_members[${member}]=1;
    done
    echo ${!ckb_workspace_members[@]}


    for cargo_toml in ${CARGOS}; do
        local package_name=$(tomlq .package.name "${cargo_toml}")
        local space_indent='                                  '
        printf "Checking %s %s: %s\n" "${package_name}" "${space_indent:${#package_name}}"  "${cargo_toml}"
        if [ "${cargo_toml}" = "${SRC_ROOT}/Cargo.toml" ] || [ "${cargo_toml}" = "${SRC_ROOT}/test/Cargo.toml" ] || [ "${cargo_toml}" = "${SRC_ROOT}/network/fuzz/Cargo.toml" ] || [ "${cargo_toml}" = "${SRC_ROOT}/script/fuzz/Cargo.toml" ]; then
            dep_version=$(cat "${SRC_ROOT}/Cargo.toml" | tomlq -r .package.version)

            # check dep_version == ckb_version
            if [ "${dep_version}" != "${ckb_version}" ]; then
                ERRCNT=$((ERRCNT + 1))
                printf "Error in: %s. version(%s) != ckb worksapce version(%s)" "${cargo_toml}" "${dep_version}" "${ckb_version}"
                exit 1
            fi

        else
            tomlq -e '.package.version.workspace == true' "${cargo_toml}" > /dev/null
            if [ $? -ne 0 ]; then
                ERRCNT=$((ERRCNT + 1))
                printf "Error %s 's version not inherit from ckb worksapce" "${cargo_toml}"
            fi
        fi

        deps=$(cargo tree --depth 1 --manifest-path "${cargo_toml}" --prefix none)
        if [ $? -ne 0 ]; then
            ERRCNT=$((ERRCNT + 1))
            printf "Error %s 's version not inherit from ckb worksapce" "${cargo_toml}"
        fi

        while IFS= read -r dep; do
            dep_name=$(echo ${dep} | awk -F' ' '{print $1}')
            dep_version=$(echo ${dep} | awk -F' ' '{print $2}')
            if [[  -v ckb_workspace_members["${dep_name}"] ]]; then
                # thes dep is a ckb's workspace member
                # if dep_version not equal to ckb's version, then it's an error
                if [ "${dep_version}" != "v${ckb_version}" ]; then
                    ERRCNT=$((ERRCNT + 1))
                    printf "Error in: %s. %s's version(%s) != ckb worksapce version(%s)" \
                           "${cargo_toml}" "${dep_name}" \
                           "${dep_version}" "v${ckb_version}"
                    exit 1
                fi
            fi
        done <<< "$deps"




    done
}

function check_license() {
  local regex_to_cut_license='s/^license = "\(.*\)"$/\1/p'
  local expected=$(${SED} -n "${regex_to_cut_license}" "${SRC_ROOT}/Cargo.toml")
  for cargo_toml in ${CARGOS}; do
    local tmp=$(${SED} -n "${regex_to_cut_license}" "${cargo_toml}")
    if [ "${expected}" != "${tmp}" ]; then
      printf "Error: License in <%s> is not right (expect: '%s', actual: '%s')\n" \
        "${cargo_toml}" "${expected}" "${tmp}"
      ERRCNT=$((ERRCNT + 1))
    fi
  done
}

function check_cargo_publish() {
  for cargo_toml in ${CARGOS}; do
    if ! grep -q '^description =' "${cargo_toml}"; then
      echo "Error: Require description in <${cargo_toml}>"
      ERRCNT=$((ERRCNT + 1))
    fi
    if ! grep -q '^homepage =' "${cargo_toml}"; then
      echo "Error: Require homepage in <${cargo_toml}>"
      ERRCNT=$((ERRCNT + 1))
    fi
    if ! grep -q '^repository =' "${cargo_toml}"; then
      echo "Error: Require repository in <${cargo_toml}>"
      ERRCNT=$((ERRCNT + 1))
    fi
  done
}

function check_dependencies() {
  if ! type cargo-shear &> /dev/null
  then
      # lock version to avoid breaking building now
      cargo install cargo-shear --version 1.1.10
  fi
  cargo shear
}

function main() {
  echo "[BEGIN] Checking Cargo.toml ..."
  check_package_name
  check_version
  check_license
  check_cargo_publish
  check_dependencies
  echo "[ END ] Found ${ERRCNT} errors."
  if [ "${ERRCNT}" -ne 0 ]; then
    exit 1
  fi
}

main "$@"
