#!/bin/bash

###
# Usage:
#   bin/checker [branch] [type] [fix]
#
#   branch:
#     > master   - use branch origin/master as base for diff
#       <branch> - use branch origin/<branch> as base for diff
#
#   type:
#     > diff    - all files in repository
#       default - diff of all changed files (staged and unstaged)
#       staged  - diff of only staged files
#
#   fix:
#     > nofix   - no fix
#       fix     - run fix
###

BRANCH="${1:-master}"
TYPE="${2:-diff}"
FIX="${3:-nofix}"

DIR="$(pwd)/vendor/banovo/coding-standard"

###
# Setup colors
###

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[1;34m'
GRAY='\033[1;30m'
NC='\033[0m' # No Color

###
# Define functions
###

function section {
    echo
    echo -e "${BLUE}$1${NC}"
    echo
}

function skip {
    echo -e "${GRAY}$1${NC}"
}

function command {
    echo
    echo -e "${YELLOW}$1${NC}"
}

function success {
    echo
    echo -e "${GREEN}$1${NC}"
}

function failure {
    echo
    echo -e "${RED}$1${NC}"
}

let "ERROR_COUNT=0"

###
# PHP checks
###

case "$TYPE" in
    all)
        FILES_ALL=$(git ls-files | grep -e '^src\|^tests' | grep -v 'lib' | grep -v 'vendor')
        ;;
    staged)
        FILES_ALL=$(git diff origin/$BRANCH...HEAD --diff-filter=ACM --name-only)
        ;;
    diff)
        FILES_ALL=$(git diff --name-only --diff-filter=ACM origin/$BRANCH)
        ;;
esac

section "CHANGES"
printf ' - %s\n' $FILES_ALL

FILES_PHP=$(printf '%s\n' $FILES_ALL | grep '\.php$')
FILES_PHP_FILTERED=$(printf '%s\n' $FILES_PHP | grep -v 'Migrations' | grep -v 'Tests')
FILES_JS=$(printf '%s\n' $FILES_ALL | grep -e '\.js$' -e '\.vue$' -e '\.twig$' -e '\.html$')

section "PHP CHECKS"

if [ -z "$FILES_PHP" ];
then
    skip "Skipping php check: no php file was changed"
else
    command "Syntax check"
    for f in $FILES_PHP
    do
        php -l $f 1> /dev/null
        [ $? -ne 0 ] && let "ERROR_COUNT++"
    done

    if [ "$FIX" == "fix" ];
    then
        command "Coding Standards Fixer"
        bin/php-cs-fixer fix --config=$DIR/rulesets/.php_cs.dist --stop-on-violation --show-progress=none --using-cache=no --path-mode=intersection -- $FILES_PHP
        [ $? -ne 0 ] && let "ERROR_COUNT++"

        command "Code Beautifier and Fixer"
        bin/phpcbf $FILES_PHP --standard=$DIR/rulesets/phpcs.xml
        [ $? -ne 0 ] && let "ERROR_COUNT++"
    fi

    command "Coding Standards"
    bin/phpcs $FILES_PHP -s --standard=$DIR/rulesets/phpcs.xml
    [ $? -ne 0 ] && let "ERROR_COUNT++"

    command "Copy/Paste Detector"
    bin/phpcpd $FILES_PHP_FILTERED
    [ $? -ne 0 ] && let "ERROR_COUNT++"

    command "Mess Detector"
    for f in $FILES_PHP
    do
        bin/phpmd $f text $DIR/rulesets/pmd.xml
        [ $? -ne 0 ] && let "ERROR_COUNT++"
    done
fi

###
# Javascript checks
###

section "JS CHECKS"

if [ -z "$FILES_JS" ];
then
    skip "Skipping js check: no js/vue/twig/html file was changed"
else
    if [ "$FIX" == "fix" ];
    then
        command "Syntax and automatically fix problems"
        node_modules/.bin/eslint $FILES_JS --ext js,vue --fix
        [ $? -ne 0 ] && let "ERROR_COUNT++"
    else
        command "Syntax"
        node_modules/.bin/eslint $FILES_JS --ext js,vue
        [ $? -ne 0 ] && let "ERROR_COUNT++"
    fi
fi

if [ $ERROR_COUNT -ne 0 ] ;
then
    failure "Checking failed. Found $ERROR_COUNT errors"
    exit 1
fi

success "Checking completed"
exit 0
