@echo off
setlocal EnableDelayedExpansion

set SCRIPT_NAMES=musicXmlValidate musicXmlCompress musicXml2Db db2MusicXml musicXmlDiff db2Ly db2Pdf ly2Pdf musicXml2Ly musicXml2Pdf
set OUTPUT_SCRIPT_NAMES=musicXmlCompress db2MusicXml musicXmlDiff db2Ly db2Pdf ly2Pdf musicXml2Ly musicXml2Pdf

call "%~dp0musicXmlConfig"

goto :init

:help
    call :usage
    @echo.
    echo The musicXmlBulk script calls one or more processing scripts on any combination of files, directories of files,
    echo score names, and score IDs in one go.
    @echo.
    echo In most cases, musicXmlBulk processes the input and formulates calls to the musicXmlProcess script,
    echo so many of the rules that apply to musicXmlProcess apply to musicXmlBulk.
    @echo.
    echo SCRIPT_NAME_VALUE: a single script name, or script name wildcard.
    @echo.
    echo The bulk script will call combinations of the following scripts:
    @echo.
    echo db2Ly
    echo db2MusicXml
    echo db2Pdf
    echo ly2Pdf
    echo musicXml2Db
    echo musicXml2Ly
    echo musicXml2Pdf
    echo musicXmlCompress
    echo musicXmlValidate
    @echo.
    echo SCRIPT_NAME_VALUE examples:
    @echo.
    echo musicXml2Db: will execute the musicXml2Db script on each XML file in the input file list.
    @echo.
    echo musicXml2.*: will execute each of the three musicXml2* scripts on each XML file in the input file list.
    @echo.
    echo .* will execute all of the scripts on every eligible value in the input list.
    @echo.
    echo Options:
    echo /f, --input-file	input file
    echo /i, --input-directory		input directory
    echo /o, --output-directory		output directory
    @echo.
    echo Input options:
    @echo.
    echo The input options direct the bulk script which files to process.
    @echo.
    echo Input values can be a single directory (option -i), a list of input values in a file (option -f), or both.
    @echo.
    echo Input directory option:
    @echo.
    echo The script takes a single input directory as an argument.
    @echo.
    echo All .xml, .mxl, .musicxml, and .ly files in the directory are added to the input list.
    @echo.
    echo Input file option:
    @echo.
    echo The input file is a text file that lists input values, one to a line.
    @echo.
    echo Input line values can be any combination of the following:
    @echo.
    echo   An input filename
    echo   An input directory
    echo   An input score name
    echo   A comma-separated input score ID or score ID range
    @echo.
    echo Wild cards in input values are not permitted.
    @echo.
    echo Input value processing:
    @echo.
    echo An input filename is added to the input list if it has an .xml, .mxl, .musicxml, or .ly
    echo file extension.
    @echo.
    echo If an input line is a directory, all .xml, .mxl, .musicxml, and .ly files in the directory are added
    echo to the input list.
    @echo.
    echo Score IDs refer to the primary key ID value in the SCORE table in the MusicXML database.
    @echo.
    echo Valid score ID input is a comma-separated list of numbers or range of numbers.
    echo Example: 2,4,6-10
    @echo.
    echo Any non-numeric item in the file list that does not have a file extension is treated as a
    echo score name and is added to the input list.
    @echo.
    echo Input for each script:
    @echo.
    echo Once input processing is finished, the result is an input list of filenames, score names, and/or score IDs.
    @echo.
    echo musicXml* script input: All XML file input (.xml, .mxl, and .musicxml file extensions).
    @echo.
    echo musicXmlCompress script input:  All uncompressed XML file input (.xml and .musicxml file extensions).
    @echo.
    echo db2* script input: All score names and score IDs.
    @echo.
    echo Additionally, the filenames of all .xml, .mxl, .musicxml, and .ly files in the input list are truncated by
    echo removing the file extension, and the file's basename is treated as a score name.  The script then attempts
    echo to process any score in the database having that score name.
    @echo.
    echo ly2Pdf script input:  All LilyPond file input (.ly file extension).
    @echo.
    echo Output for each script:
    @echo.
    echo The output directory option is required for all scripts except musicXmlValidate and musicXml2Db.
    @echo.
    echo Verbose output is used for all scripts except musicXmlCompress and musicXmlValidate.  Script output
    echo is to stderr and can be redirected by the caller.
    @echo.
    echo Output subdirectories:
    @echo.
    echo The output directory passed by the output directory option must exist before the call to musicXmlBulk.
    @echo.
    echo Script output is to a subdirectory of the passed output directory, one subdirectory for each script called.
    @echo.
    echo The subdirectories are:
    echo Script db2Ly: subdirectory db2ly
    echo Script db2MusicXml: subdirectory db2musicxml
    echo Script db2Pdf: subdirectory db2pdf
    echo Script ly2Pdf: subdirectory ly2pdf
    echo Script musicXml2Ly: subdirectory musicxml2ly
    echo Script musicXml2Pdf: subdirectory musicxml2pdf
    echo Script musicXmlCompress: subdirectory xmlcompress
    @echo.
    echo The directory separation is so that multiple script calls that result in the same file type output
    echo don't overwrite each other.
    @echo.
    echo Example:
    echo Output directory: musicxml/out
    echo db2MusicXml script output directory: musicxml/out/db2musicxml
    @echo.
    echo Output filenames:
    @echo.
    echo All XML script output is an .xml file, except for musicXmlCompress which outputs an .mxl file.
    @echo.
    echo The XML file in a compressed MXL file has the same basename as the containing MXL file.
    @echo.
    echo The basename of the output file is the basename of the input file.
    @echo.
    echo In the case of db2* scripts, the output file's basename is the score name or the score ID,
    echo depending upon which is being processed.
    exit /b 0
:usage
    echo Usage: musicXmlBulk [OPTIONS] SCRIPT_NAME_VALUE
    exit /b
:error_message
    set message=%*
    set message=%message:"=%
    echo %message% >&2
    call :usage
    exit /b 1
:init
    set VERBOSE=/v
    set INPUT_FILES=
    set XML_FILES=
    set LY_FILES=
    set INPUT_FILE=
    set SCORENAMES=
    set INPUT_DIRECTORY=
    set OUTPUT_DIRECTORY=
    set OUTPUT_DIRECTORY_REQUIRED=
    set SCRIPT_NAME_MATCH=

    set /a INPUT_INDEX=0
    set RUN=

:arguments
    set ARGUMENT=%~1
    if "%ARGUMENT%"=="" goto :check_script_list
    if "%ARGUMENT%"=="/f" set INPUT_FILE=%~2 & shift & shift & goto :arguments
    if "%ARGUMENT%"=="--input-file" set INPUT_FILE=%~2 & shift & shift & goto :arguments
    if "%ARGUMENT%"=="/i" set INPUT_DIRECTORY=%~2& shift & shift & goto :arguments
    if "%ARGUMENT%"=="--input-directory" set INPUT_DIRECTORY=%~2& shift & shift & goto :arguments
    if "%ARGUMENT%"=="/o" set OUTPUT_DIRECTORY=%~2& shift & shift & goto :arguments
    if "%ARGUMENT%"=="--output-directory" set OUTPUT_DIRECTORY=%~2& shift & shift & goto :arguments
    if "%ARGUMENT%"=="/h" shift & goto :help
    if "%ARGUMENT%"=="--help" shift & goto :help
    if "%ARGUMENT:~0,1%"=="/" call :error_message "Unrecognized argument: %ARGUMENT%" & exit /b 1
    if "%ARGUMENT:~0,2%"=="--" call :error_message "Unrecognized argument: %ARGUMENT%" & exit /b 1

    set ARGUMENT=%~1
    if %ARGUMENT%=="" goto :check_script_list
    set SCRIPT_NAME_MATCH=%ARGUMENT%

    for %%S in (%SCRIPT_NAMES%) do (set "SCRIPT_NAME=%%S" & call :find_run_items)
    shift
    goto :arguments

:find_run_items
    echo(%SCRIPT_NAME%|findstr /r /c:"%SCRIPT_NAME_MATCH%" >nul && call :set_run_item
    exit /b
:set_run_item
    set /a INPUT_INDEX+=1
    set RUN[%INPUT_INDEX%]=%SCRIPT_NAME%
    for %%S in (%OUTPUT_SCRIPT_NAMES%) do (
        if "%SCRIPT_NAME%"=="%%S" set OUTPUT_DIRECTORY_REQUIRED=true& exit /b
    )
    exit /b
:check_script_list
    if %INPUT_INDEX%==0 echo Script name not indicated & exit /b 1
    if "%OUTPUT_DIRECTORY%"=="" (
        if defined OUTPUT_DIRECTORY_REQUIRED echo Output directory vaLue required & exit /b 1
    )

    if defined INPUT_DIRECTORY (
        set INPUT_DIRECTORY=%INPUT_DIRECTORY:"=%
        for /f "delims=" %%f in ('dir /s /b "%INPUT_DIRECTORY%\*.xml" "%INPUT_DIRECTORY%\*.mxl" "%INPUT_DIRECTORY%\*.musicxml" "%INPUT_DIRECTORY%\*.ly"') do (
            set INPUT_FILES=!INPUT_FILES! "%%f"
        )
        for %%S in (!INPUT_FILES!) do (
            set SCORENAMES=!SCORENAMES! %%~nS
        )
    )
    if defined INPUT_FILE (
        for /F "usebackq delims=" %%A in ("%INPUT_FILE%") do (
            call :input_file_check "%%A"
        )
    )

    for %%S in (%INPUT_FILES%) do (
        if "%%~xS"==".xml" set XML_FILES=!XML_FILES! %%S
        if "%%~xS"==".mxl" set XML_FILES=!XML_FILES! %%S
        if "%%~xS"==".musicxml" set XML_FILES=!XML_FILES! %%S
        if "%%~xS"==".ly" set LY_FILES=!LY_FILES! %%S
    )

    for /L %%I in (1,1,%INPUT_INDEX%) do (
        set /a RUN_INDEX=%%I
        call :execute_script
    )

    exit /b

:input_file_check
    set FILENAME=%~1
    set FILE_ATTRIBUTE=%~a1
    if "%FILE_ATTRIBUTE:~0,1%"=="d" (
        for /f "delims=" %%f in ('dir /s /b "%FILENAME%\*.xml" "%FILENAME%\*.mxl" "%FILENAME%\*.musicxml" "%FILENAME%\*.ly"') do (
            set INPUT_FILES=!INPUT_FILES! "%%f"
        )
        for %%S in (!INPUT_FILES!) do (
            set SCORENAMES=!SCORENAMES! %%~nS
        )
        exit /b
    )

    set INPUT_FILES=!INPUT_FILES! "%FILENAME%"
    for %%S in (%FILENAME%) do set SCORENAMES=!SCORENAMES! %%~nS
    exit /b

:execute_script
    set SCRIPT_NAME=!RUN[%RUN_INDEX%]!

    if "!RUN[%RUN_INDEX%]!"=="musicXmlValidate" (
        for %%S in (%XML_FILES%) do (
            echo musicXmlValidate: %%S
            call musicXmlValidate %%S
        )
    )

    if "!RUN[%RUN_INDEX%]!"=="musicXmlCompress" (
        set COMPRESSOUTDIR="%OUTPUT_DIRECTORY%\xmlcompress"
        if not exist !COMPRESSOUTDIR!\ mkdir !COMPRESSOUTDIR!
        set COMPRESSOUTDIR=!COMPRESSOUTDIR:"=!
        for %%S in (%XML_FILES%) do (
            if not "%%~xS"==".mxl" (
                echo musicXmlCompress: %%S
                call musicXmlCompress %%S "!COMPRESSOUTDIR!\%%~nS.mxl"
            )
        )
    )

    if "!RUN[%RUN_INDEX%]!"=="musicXml2Db" (
        call musicXmlProcess /v musicXml2Db %XML_FILES%
    )

    if "!RUN[%RUN_INDEX%]!"=="db2MusicXml" (
        set DB2MUSICXMLOUTDIR="%OUTPUT_DIRECTORY%\db2musicxml"
        if not exist !DB2MUSICXMLOUTDIR!\ mkdir !DB2MUSICXMLOUTDIR!
        call musicXmlProcess /v db2MusicXml !DB2MUSICXMLOUTDIR! %SCORENAMES%
    )

    if "!RUN[%RUN_INDEX%]!"=="db2Ly" (
        set DB2LYOUTDIR="%OUTPUT_DIRECTORY%\db2ly"
        if not exist !DB2LYOUTDIR!\ mkdir !DB2LYOUTDIR!
        call musicXmlProcess /v db2Ly !DB2LYOUTDIR! %SCORENAMES%
    )

    if "!RUN[%RUN_INDEX%]!"=="db2Pdf" (
        set DB2PDFOUTDIR="%OUTPUT_DIRECTORY%\db2pdf"
        if not exist !DB2PDFOUTDIR!\ mkdir !DB2PDFOUTDIR!
        call musicXmlProcess /v db2Pdf !DB2PDFOUTDIR! %SCORENAMES%
    )

    if "!RUN[%RUN_INDEX%]!"=="ly2Pdf" (
        set LY2PDFOUTDIR="%OUTPUT_DIRECTORY%\ly2pdf"
        if not exist !LY2PDFOUTDIR!\ mkdir !LY2PDFOUTDIR!
        call musicXmlProcess /v ly2Pdf !LY2PDFOUTDIR! %LY_FILES%
    )

    if "!RUN[%RUN_INDEX%]!"=="musicXml2Ly" (
        set MUSICXML2LYOUTDIR="%OUTPUT_DIRECTORY%\musicxml2ly"
        if not exist !MUSICXML2LYOUTDIR!\ mkdir !MUSICXML2LYOUTDIR!
        call musicXmlProcess /v musicXml2Ly !MUSICXML2LYOUTDIR! %XML_FILES%
    )

    if "!RUN[%RUN_INDEX%]!"=="musicXml2Pdf" (
        set MUSICXML2PDFOUTDIR="%OUTPUT_DIRECTORY%\musicxml2pdf"
        if not exist !MUSICXML2PDFOUTDIR!\ mkdir !MUSICXML2PDFOUTDIR!
        call musicXmlProcess /v musicXml2Pdf !MUSICXML2PDFOUTDIR! %XML_FILES%
    )

    exit /b
