#!/usr/bin/env bash

# Requirements
# - Chef workstation
# - Access to chef server
# - Knife block plugin with configured sites
# - Berks plugin 
# - git, jsonlint, and other binaries listed below.
# - This script should be called from the base directory of the chef-repo repository

set -ex

KNIFE_BINARY=$(/usr/bin/which knife)
BERKS_BINARY=$(/usr/bin/which berks)
GIT_BINARY=$(/usr/bin/which git)
JSONLINT_BINARY=$(/usr/bin/which jsonlint)
RUBOCOP_BINARY=$(/usr/bin/which rubocop)
KNIFE_BLOCK_VERSION=$(chef gem list --local | grep knife-block)

set +x

if [ -x ${KNIFE_BINARY} ] && [ -x ${BERKS_BINARY} ] && [ -x ${GIT_BINARY} ] && [ -x ${JSONLINT_BINARY} ] && [ -x ${RUBOCOP_BINARY} ] && [[ ${KNIFE_BLOCK_VERSION} =~ "knife-block" ]]; then 
  printf '%s\n' "Berks, knife, git, jsonlint, rubocop binaries and knife-block plugin found. Continuing..."
  printf '%s\n'
else
  printf '%s\n' "Berks, knife, git, jsonlint, rubocop binaries or knife-block plugin not found or executable." && exit 1
fi

LATEST_COMMIT=$(git rev-parse HEAD)
PREVIOUS_COMMIT=$(git rev-parse HEAD~1)

printf '%s\n' "Checking revision ${LATEST_COMMIT} against ${PREVIOUS_COMMIT}"
printf '%s\n'
CHANGED_FILES="$(${GIT_BINARY} diff-tree --no-commit-id --name-only -r ${LATEST_COMMIT} ${PREVIOUS_COMMIT})"
printf '%s\n' "Changed files are:" ${CHANGED_FILES}
printf '%s\n'

for file in ${CHANGED_FILES}; do
  # Skip encrypted data bags
  if [[ ${file} =~ ^data_bags/secrets ]]; then 
    printf '%s\n' "Secret data bag found. Skipping..."
    printf '%s\n'
  else
    # Proceed with all other files
    if [[ "${file}" == *.rb ]]; then
      printf '%s\n' "Ruby file detected. Checking with Rubocop..."
      printf '%s\n'
      if $(${RUBOCOP_BINARY} ${file} | grep -q "no offenses"); then
        printf '%s\n' "Rubocop passed for ${file}."
        printf '%s\n'
      else
        printf '%s\n' "Rubocop detected an error in ${file}." && exit 1
      fi
    elif [[ "${file}" == *.json ]]; then
      printf '%s\n' "JSON file detected. Linting json for ${file}..."
      printf '%s\n'
      if $(${JSONLINT_BINARY} ${file} 2>&1 -q | grep -q "Error"); then 
        printf '%s\n' "JSON error in ${file}" && exit 1
      else
        printf '%s\n' "JSON lint passed for ${file}."
        printf '%s\n'
      fi
    elif [[ "${file}" == *.md ]]; then
      printf '%s\n' "Markdown file detected. Moving along..."
      printf '%s\n'
    else
      printf '%s\n' "Unsupported file type detected. Only JSON and Ruby are supported." && exit 1
    fi
    
    for site in $(${KNIFE_BINARY} block list | grep -i '*' | awk '{print $2}'); do
      ${KNIFE_BINARY} block use "${site}"

      RESOURCE_TYPE=$(printf '%s\n' "${file}" | cut -d '/' -f 1)
      if ${KNIFE_BINARY} ${RESOURCE_TYPE%?} from file ${file}; then
        printf '%s\n' "Successfully updated ${file} on ${site}."
        printf '%s\n'
      else
        printf '%s\n' "Error updating ${file} on ${site}." && exit 1
      fi
    done
  fi
done
