# -*-Shell-script-*-
#
# Copyright (C) 2015-2020 SUSE Software Solutions Germany GmbH
#
# Author:
# Frank Sundermeyer <fsundermeyer at opensuse dot org>
#
###########################################################################
#
#  SPELLCHECK
#
#  Spellchecks a file specified with -f or --file or
#  the document specified by rootid.
#
###########################################################################

function spellcheck {
    local SHORT_OPTS LONG_OPTS SUB_CMD
    local COUNT FILE LISTMODE LISTOUTPUT LIST_PARAM OPEN_PARAM SC
    local SPELLCMD SPELL_CHECKER_CMD
    local -a FILELIST SKIPLIST

    SUB_CMD=$1
    shift

    SHORT_OPTS="h"
    LONG_OPTS="extra-dict:,file:,help,lang:,list,rootid:,spellchecker:"

    parse_args "$SHORT_OPTS" "$LONG_OPTS" "$SUB_CMD" "$@"
    eval set -- "$P_REMAIN_ARGS"

    # checker was provided on the command line
    if [[ -n "$SPELL_CHECKER" ]]; then
        # check whether the given spellchecker is valid
        [[ "aspell" = $SPELL_CHECKER || "hunspell" = $SPELL_CHECKER ]] || \
            exit_on_error "Wrong value for --spellchecker. Needs to be \"aspell\" or \"hunspell\""
        # check whether given spellchecker is installed:
        [[ $(which --skip-alias --skip-functions "$SPELL_CHECKER" 2>/dev/null) ]] || ccecho "error" "Error: '$SPELL_CHECKER' is not installed"
    else
        if [[ -z "$SPELL_CHECKER" ]]; then
            # no spell checker defined in the configs or on the command line
            # searching for aspell or hunspell
            # If both are installed, favor aspell
            for SC in aspell hunspell; do
                SPELL_CHECKER="$(which  --skip-alias --skip-functions "$SC" 2>/dev/null)"
                [[ -n "$SPELL_CHECKER" ]] && break;
            done
            [[ -z "$SPELL_CHECKER" ]] && exit_on_error "Cannot perform a spell check; neither aspell nor hunspell is installed"
        fi
    fi

    #------ Computing the values returned from the parser -----
    if [[ 1 -eq $P_HELP ]]; then
        help_scmd_head "$SUB_CMD" "${HELP_SUBCOMMAND[$SUB_CMD]}"
        help_extra-dict
        help_file
        help_help
        help_lang
        help_list
        help_rootid
        help_spellchecker
        echo -e "    NOTES: * Options --file (-f) and --rootid exclude one another.\n           * If neither file nor rootid is specified, the rootid\n             from the DC-file is used\n           * $SUB_CMD follows xi:includes\n"
        exit 0
    fi

    [[ -n "$P_FILE" ]] && FILELIST[0]="$P_FILE"

    # set FILELIST if rootid was specified
    if [[ -z "$P_ROOTID" && -z "$P_FILE" ]]; then
        if [[ 0 -ne $VERBOSITY ]]; then
            ccecho "info" "Neither file nor rootid specified, using rootid from DC-file"
        fi
    elif [[ -n "$P_ROOTID" && -n "$P_FILE" ]]; then
        exit_on_error "Options --file and --rootid exclude one another.\nPlease specify only one of these options"
    fi

    if [[ -z "${FILELIST[0]}" ]]; then ## --file was not specified
        FILELIST=( $(call_make list-srcfiles silent LIST_NODC=1 LIST_NOENT=1 LIST_NOIMG=1 ) )
        if [[ 0 -ne $? ]]; then
            exit_on_error "Failed to get filelist for ROOTID \"$ROOTID\""
        fi
    fi

    # Set language - if not specified anywhere try to get from $MAIN
    #
    if [[ -n "$P_LANG" ]]; then
        SPELL_LANG="$P_LANG"
    else
        if [[ -z "$SPELL_LANG" ]]; then
            SPELL_LANG=$($XSLTPROC --stylesheet "${DAPSROOT}/daps-xslt/common/get-language.xsl" --file "$MAIN" "$XSLTPROCESSOR" 2>/dev/null)
            if [[ -n "$SPELL_LANG" ]]; then
                ccecho "info" "Using language $SPELL_LANG."
            else
                exit_on_error "Failed to get language from $MAIN. Please specify it with --lang."
            fi
        fi
    fi

    #------------------
    # create spellchecking command for both aspell and hunspell
    #

    # first, create skiplist for aspell (not supported by hunspell)
    if [[ "aspell" = ${SPELL_CHECKER##*/} ]]; then
        COUNT=0
        for SKIP in $SPELL_SKIP_TAGS; do
            SKIPLIST[$COUNT]="--add-sgml-skip=$SKIP"
        let COUNT++
        done
    fi
    # second, create the command
    case "${SPELL_CHECKER##*/}" in
        aspell )
            # check and sanitize path to extra-dict
            sanitize_path "$2" "SPELL_EXTRA_DICT"
            # create skiplist (not supported by hunspell)
            COUNT=0
            for SKIP in $SPELL_SKIP_TAGS; do
                SKIPLIST[$COUNT]="--add-sgml-skip=$SKIP"
                let COUNT++
            done
            SPELLCMD="$SPELL_CHECKER --mode=sgml ${SKIPLIST[*]} --encoding=utf-8 --lang=$SPELL_LANG"
            if [[ -n "$SPELL_EXTRA_DICT" ]]; then
                SPELLCMD+=" --extra-dicts=$SPELL_EXTRA_DICT"
            fi
            OPEN_PARAM=" -c"
            LIST_PARAM="list"
            ;;
        hunspell )
            # check language
            if [[ ! "$SPELL_LANG" =~ ^[a-z][a-z]_[A-Z][A-Z]$ ]]; then
                if [[ -n "$P_LANG" ]]; then
                    exit_on_error "Wrong data format for --lang; must be xx_XX, e.g. en_US"
                else
                    exit_on_error "Could not automatically determine correct language parameter\n(Format must be xx_XX, e.g. en_US), please specify it with --lang"
                fi
            fi
            SPELLCMD="$SPELL_CHECKER -H -i utf-8 -d $SPELL_LANG"
            if [[ -n "$SPELL_EXTRA_DICT" ]]; then
                SPELLCMD+=",$SPELL_EXTRA_DICT"
            fi
            LIST_PARAM="-l"
            ;;
    esac

    # show spellchecker command with --debug
    [[ 1 -eq $DEBUG ]] && echo "DEBUG: $SPELLCMD"

    # do spellchecking on the list of files
    for FILE in "${FILELIST[@]}"; do
        test -f "$FILE" || ccecho "warn" "File $FILE does not exist"
        if [[ 1 -eq $LISTMODE ]]; then
            LISTOUTPUT=$($SPELLCMD $LIST_PARAM < "$FILE" | sort -u 2>/dev/null)
            [[ -n "$LISTOUTPUT" ]] && echo -e "$FILE\n------------------------------\n$LISTOUTPUT\n"
            LISTOUTPUT=""
        else
            echo "Checking $FILE..."
            $SPELLCMD $OPEN_PARAM $FILE
        fi
    done
    exit
}
