#!/usr/bin/env bash

pushd "$DOTFILES/sh/templates/" &>/dev/null || exit 1

mkdir -p "$DOTFILES/cron/generated/"
for job in report-summary annex backup copy-box-backups repo-update mbox-archive mr-remotes-backup; do
  sed "s/__JOB__/$job/" cronjob-with-email.sh > "$HOME/dev/libre/dotfiles/cron/generated/$job-job.sh"
  chmod +x "$HOME/dev/libre/dotfiles/cron/$job.sh"
  chmod +x "$HOME/dev/libre/dotfiles/cron/generated/$job-job.sh"
done

mkdir -p "$HOME/annex/bin/cron/generated/"
# shellcheck disable=2043
for job in pacheco; do
  prefix="$HOME/annex/bin/cron"
  sed "s/__JOB__-job/$job-job/" cronjob-with-email.sh | sed "s|.*__JOB__.*|$prefix/$job.sh|" > "$HOME/annex/bin/cron/$job-job.sh"
  chmod +x "$HOME/annex/bin/cron/$job.sh"
  chmod +x "$HOME/annex/bin/cron/generated/$job-job.sh"
done

cp ~/dev/libre/package-repository/EuAndreh.key ~/dev/libre/website/public-key.txt

mkdir -p ~/archive/torrent/
find ~/dev/libre/website/ -type f -name '*.torrent' -exec cp {} ~/archive/torrent/ \;

normalize_name() {
  if [ -n "$RENAME_TO" ]; then
    echo "$RENAME_TO"
  elif [[ "$1" = ..* ]]; then
    echo "${1:1}"
  else
    echo "$1"
  fi
}

cp_all() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    mkdir -p "$(dirname "$OUT")"
    cp "$f" "$OUT"
  done
}

cp_if_not() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    if [ ! -f "$OUT" ]; then
      cp_all "$f"
    fi
  done
}

cp_if() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    if [ -f "$OUT" ]; then
      rm -f "$OUT"
      cp_all "$f"
    fi
  done
}

envsubst_all() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    mkdir -p "$(dirname "$OUT")"
    envsubst < "$f" > "$OUT"

    if [ -n "$EXECUTABLE" ]; then
      chmod +x "$OUT"
    fi
  done
}

envsubst_if_not() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    if [ ! -f "$OUT" ]; then
      envsubst_all "$f"
    fi
  done
}

sed_all() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    mkdir -p "$(dirname "$OUT")"

    if [ -n "$ENABLE_CI" ]; then
      ENABLE_CI_SCRIPT='s/__ENABLE_CI__ //g'
      if [ -n "$ENABLE_AUTOTOOLS" ]; then
        TLD_SCRIPT=''
      else
        TLD_SCRIPT="$DEFAULT_TLD_SCRIPT"
      fi
    else
      ENABLE_CI_SCRIPT='/__ENABLE_CI__ /d'
      TLD_SCRIPT="$DEFAULT_TLD_SCRIPT"
    fi

    sed "$f"                                    \
        -e "s/__PROJECT_UC__/$PROJECT_UC/g"     \
        -e "s/__PROJECT__/$PROJECT/g"           \
        -e "s/__MAILING_LIST__/$MAILING_LIST/g" \
        -e "$TLD_SCRIPT"                        \
        -e "$ENABLE_CI_SCRIPT"                  \
        -e "$ENABLE_AUTOTOOLS_SCRIPT"           \
        > "$OUT"

    if [ -n "$EXECUTABLE" ]; then
      chmod +x "$OUT"
    fi
  done
}

sed_if_not() {
  for f in "$@"; do
    OUT="$PREFIX/$(normalize_name "$f")"
    if [ ! -f "$OUT" ]; then
      sed_all "$f"
    fi
  done
}

ln_env() {
  export PROJECT="$1"
  export PREFIX="${PREFIX_FOR_PROJECT[$PROJECT]:-$HOME/dev/libre/$PROJECT}"
  export MAILING_LIST="${ML_FOR_PROJECT[$PROJECT]:-public-inbox}"
  export PROJECT_UC="${PROJECT_NAMES[$PROJECT]:-$PROJECT}"

  if [ -f "$PREFIX/Makefile.in" ] || [ -f "$PREFIX/Makefile" ]; then
    export ENABLE_CI=1
  else
    export ENABLE_CI=
  fi

  if [ -n "${GUILE_PROJECTS[$PROJECT]}" ]; then
    ENABLE_GUILE=1
  else
    ENABLE_GUILE=
  fi

  if [ -n "${C_PROJECT[$PROJECT]}" ]; then
    ENABLE_C=1
  else
    ENABLE_C=
  fi

  if [ -f "$PREFIX/aux/guix/pinned-channels.scm" ] &&
       [ "$(wc -l < "$PREFIX/aux/guix/pinned-channels.scm")" = 10 ]; then
    ENABLE_OVERWRITE_PINNED_CHANNELS=1
  else
    ENABLE_OVERWRITE_PINNED_CHANNELS=
  fi

  if { [ -f "$PREFIX/README.md" ] || [ -f "$PREFIX/README" ]; } && [ -z "${NO_README_SH[$PROJECT]}" ]; then
    ENABLE_README_SH=1
  else
    ENABLE_README_SH=
  fi

  if [ -f "$PREFIX/CHANGELOG.md" ]; then
    ENABLE_CHANGELOG=1
  else
    ENABLE_CHANGELOG=
  fi

  if [ -f "$PREFIX/configure" ] && [ ! -x "$PREFIX/configure" ]; then
    ENABLE_CONFIGURE=1
  else
    ENABLE_CONFIGURE=
  fi
}

ln_init() {
  if ! grep -q "$PROJECT" ~/annex/bin/misc/git/mrconfig.ini; then
    red "$(printf '%s missing from mrconfig.ini!\n' "$PROJECT")\n"
  fi

  if [ ! -d "$PREFIX" ]; then
    git init "$PREFIX"
  fi
  cp_if_not description long-description
}

ln_build_aux() {
  cp_all aux/assert-shellcheck.sh     \
         aux/workflow/assert-todos.sh \
         aux/workflow/TODOs.sh        \
         aux/workflow/style.css       \
         aux/workflow/preamble.md

  if [ "$ENABLE_README_SH" ]; then
    cp_all aux/workflow/README.sh
  fi

  if [ "$ENABLE_CHANGELOG" ]; then
    cp_all aux/workflow/commonmark.sh \
           aux/workflow/dist.sh
  fi

  cp_if_not TODOs.md

  cp_if aux/assert-nixfmt.sh \
        aux/assert-perltidy.sh
}

ln_agpl() {
  cp_all COPYING
}

ln_guix_files() {
  cp_all aux/guix/with-container.sh \
         aux/assert-shellcheck.sh
  cp_if_not aux/guix/manifest.scm

  if [ -n "$ENABLE_OVERWRITE_PINNED_CHANNELS" ]; then
    cp_all aux/guix/pinned-channels.scm
  else
    cp_if_not aux/guix/pinned-channels.scm
  fi
}

ln_ci() {
  rm -f "$PREFIX/.git/hooks/pre-push"
  if [ -n "$ENABLE_CI" ]; then
    EXECUTABLE=1 sed_all aux/ci/git-pre-push.sh
    cp_all aux/assert-shellcheck.sh \
           aux/ci/ci-build.sh       \
           aux/ci/report.sh         \
           aux/ci/git-post-receive.sh
    ln -s "$PREFIX/aux/ci/git-pre-push.sh" "$PREFIX/.git/hooks/pre-push"
  else
    EXECUTABLE=1 sed_all ..git/hooks/pre-push
  fi
}

ln_git_notes_release() {
  cp_all aux/workflow/git-notes-release.sh
  cp_if_not NEWS
}

ln_dicts() {
  cp_if_not doc/dictionaries/international.txt doc/dictionaries/en.txt
}

ln_web_assets_file() {
  mkdir -p "$PREFIX/aux/"
  cp "aux/$1-build-web-assets.sh" "$PREFIX/aux/build-web-assets.sh"
}

ln_scribble() {
  ln_dicts
}

ln_antora() {
  ln_dicts
}


ln_simple_makefile() {
  if [ -n "$ENABLE_CONFIGURE" ]; then
    sed_all Makefile.in
    rm -f "$PREFIX/configure"
    cp_all configure
  else
    envsubst_if_not Makefile
  fi

  if [ -n "$ENABLE_C" ]; then
    cp_all aux/assert-clang-format.sh

    cp_if $(find -L src/vendor/ -type f) \
          tests/lib.sh \
          aux/utils.sh
  fi
}

enforce_uniform_manpages() {
  if [ -d "$PREFIX/doc" ]; then
    for f in $(find "$PREFIX/doc" -type f -name '*.[0-9]'); do
      if grep -Eq '^\.SH AUTHORS$' "$f"; then
        EXPECTED="$(cat <<EOF
.
.
.SH AUTHORS
.P
EuAndreh
.MT eu@euandre.org
.ME
and contributors.
.
.
.SH BUGS
Report bugs to:
.MT ~euandreh/$MAILING_LIST@lists.sr.ht
.ME
.br
Browse bugs at:
.UR https://$PROJECT.euandreh.xyz/TODOs.html
.UE
.br
Home page:
.UR https://$PROJECT.euandreh.xyz
.UE
.br
Discussions:
.UR https://lists.sr.ht/~euandreh/$MAILING_LIST?search=[$PROJECT]
.UE
EOF
)"
        if ! diff <(tail -n "$(wc -l <<< "$EXPECTED")" "$f") <(echo "$EXPECTED"); then
          cat "$f" <(echo "$EXPECTED") | sponge "$f"
          echo "$f"
        fi
      fi
    done
  fi
}

ln_makefile_only_project() {
  ln_env "$1"
  ln_init
  ln_agpl
  ln_ci
  ln_simple_makefile
  enforce_uniform_manpages
}

ln_makefile_only_guix_project() {
  ln_makefile_only_project "$1"
  ln_guix_files
  ln_build_aux
}

ln_bare_project() {
  ln_env "$1"
  ln_agpl
  ln_ci
}

ln_description_foreign_project() {
  ln_env "$1"
  # Foreign projects may have Makefiles and alike, and I don't want
  # to have CI files copied to the repository
  ENABLE_CI=
  ln_ci
}

declare -A PROJECT_NAMES=(
  [servers]=Servers
  [cement]=Cement
  [songbooks]=Songbooks
  [mediator]=Mediator
  [byopds]=BYOPDS
  [pires]=Pires
)

declare -A ML_FOR_PROJECT=(
  [cement]=byopds
  [byopds]=byopds
  [guile-pds]=byopds
  [x-bindgen]=mediator
  [mediator]=mediator
  [libedn]=mediator
  [konformigado]=mediator
  [gluilo]=mediator
  [fallible]=mediator
  [sharedc]=mediator
  [eq]=mediator
  [songbooks]=songbooks
  [pires]=pires
)

declare -A PREFIX_FOR_PROJECT=(
  [guix]="$HOME/dev/guix/guix"
)

declare -A GUILE_PROJECTS=(
  [guile-quickcheck]=1
  [guile-pds]=1
  [songbooks]=1
)

declare -A C_PROJECT=(
  [remembering]=1
  [gluilo]=1
  [konformigado]=1
  [libedn]=1
  [fallible]=1
  [sharedc]=1
)

declare -A NO_README_SH=(
  [website]=1
)

ln_all() {
  LN_FN="$1"
  shift
  for f in "$@"; do
    "$LN_FN" "$f"
  done
}

ln_all ln_description_foreign_project     guix               \
                                          apollo-server-demo \
                                          ml-archives        \
                                          3rd-party-archives
ln_all ln_makefile_only_project           boneco          \
                                          pdfs-da-d-maria \
                                          package-repository
ln_all ln_makefile_only_guix_project      servers          \
                                          pires            \
                                          remembering      \
                                          website          \
                                          dotfiles         \
                                          gluilo           \
                                          konformigado     \
                                          libedn           \
                                          eq               \
                                          fallible         \
                                          sharedc          \
                                          standardify      \
                                          autoqemu         \
                                          yoctoauth        \
                                          mediator         \
                                          songbooks        \
                                          cement           \
                                          guile-quickcheck \
                                          guile-pds        \
                                          byopds           \
                                          discussions-site
ln_all ln_bare_project                    brinquedoteca         \
                                          casa-do-caminho       \
                                          music                 \
                                          swift2nix             \
                                          swift2nix-demo        \
                                          cargo2nix             \
                                          cargo2nix-demo

popd &> /dev/null || exit 1
