#!/bin/tcsh 

# transforms a MAUS BPF+signal collection into an emuDB in a ZIP 
# WARNING: this script assumes that all input BPFs have the same structure!

# The script checks not for consistent files in input dir; only the found signal files
# are converted together with their annotations.


# 2016-08-31 : changed dir name of the resulting emuDB from <emuRtemplateName>
#              to <emuRtemplateName>_emuDB
# 2016-11-10 : if *_annot.json files are available instead of *.par, these are
#              used to build the emuDB and a WARNING is issued to stdout
# 2017-02-16 : changes levels names to BPF tier names (ORT,KAN,MAU)
# 2017-05-01 : if a *.wav file is missing, look for a *.nis|nist|sph file, and
#              transform this into a *.wav file for output
# 2017-05-04 : added support for optional BPF tiers KAS and MAS; syllable tier MAS
#              must be word synchronous! Replaced emuDBconfig template by in-document
#              templates; changed option emuRtemplateName to emuRDBname
# 2017-05-08 : add deprecated option emuRtemplateName again for backward compatibility,
#              bug fix in emuDBconfig: canvas MAS was always there causing an error in EMUWebAPP
# 2017-06-01 : BPFs with a single MAU tier are processed into a emuDB with a single phonetic tier
# 2017-06-02 : added option createDBConfigOnly=<path+name>, if set, the scripts only writes
#              the DBconfig.json file into the given file name and exits
# 2017-06-09 : replaced validator URL for _annot.json and added validator URL for 
#              _DBconfig.json and set validate=true as default
# 2017-07-26 : extended to handle *_annot.json and *.par files that contain only a single
#              ORT tier as delivered by runASR.
# 2017-10-25 : complete re-coding to make the script more generic
#              header, class1 and class4 parts are generated by generic code (so that all 
#              combinations are possible; ORT is preferred the class 1 level and other class 1 BPF tiers are 
#              attributes to ORT; if no ORT is found but other class 1 tiers, the first is taken as class 1 level;
#              default top level 'bundle' always has all header BPF
#              entries as attributes + default attribute 'source'; all class 4 BPF tiers are converted into levels; the link 
#              structure is fixed: bundle -> ORT -> class 4 BPF tiers or bundle -> class 4 BPF tiers; 
#              class 4 tiers may have multiple word links (e.g. TRN); class 1 tiers too, but then at least 
#              other class 1 tier without must exist, and the class 1 tier with multiple word links
#              is not an attribute but a level between bundle and class 1.
#              introduced new commandline option 'convsignal=true'; if set to false the script 
#              will not automatically convert non RIFF WAVE input signals to RIFF, but leave 
#              them as is; input signals other than wav|nis|nist|sph|mp4|mpeg|mpg are not accepted.
  
#set SOURCE = /usr/local/maus.root
set SCRIPT = `readlink -f "$0"`
set SOURCE = `dirname "$SCRIPT"`  # location where the script is stored
                           # (even if we start via a symbolic link)
set OUTZIP = ""

set v = 0

set force = FALSE
set emuRDBname = MAUSOUTPUT
# deprecated, just for backward compatibility
set emuRtemplate = ""
set validate = TRUE
#set SCHEMAANNOT = "http://webapp:9263/_annot"
set SCHEMAANNOT = "https://webapp2.phonetik.uni-muenchen.de:17890/_annot"
set SCHEMADBCONFIG = "https://webapp2.phonetik.uni-muenchen.de:17890/_DBconfig"
set createDBConfigOnly = "" 
set convsignal = "true"
set phontier = ""  # not used any more; just for backwards compatibility

# the following lists define which BPF keys are supported by the script
# !!! SYNCHRONIZE THESE LISTS WITH mausbpf2emuR !!!
set headlist = ( SAM MAO SAO REP SPN )
set class1list = ( ORT KAN KAS SPK ) # the order is the preference order for the class 1 level name!
set class1listmult = ( NOI TRL TR2 TRO ) # class 1 BPF tiers that may have multiple word links
set class4list = ( MAU PHO SAP MAS WOR TRN )

# Actually do the argument parsing here

while ( "$1" != "" )
	switch ("$1")
	case *=*:
		set key = `echo $1 | cut -d= -f1`
                #check if option is known (set)
                eval set checkoption = '$?'$key
                if ( $checkoption == 0 ) then
                  echo "ERROR: ${0:t} : unknown option $key - exiting" > /dev/stderr
                  exit 1
                endif
		set val = `echo $1 | cut -d= -f2`
		eval "set $key "= \'"$val"\'
		unset key val
		shift
		breaksw
        default:
		break
        endsw
end

# end option parser

# boolean variable check; define all boolean input parameters here

set bool = ( force validate convsignal )
foreach booleanvariable ( $bool )
  eval set val = '$'$booleanvariable
  switch ( $val )
  case true:
    eval set $booleanvariable = TRUE
    breaksw
  case True:
    eval set $booleanvariable = TRUE
    breaksw
  case TRUE:
    eval set $booleanvariable = TRUE
    breaksw
  case 1:
    eval set $booleanvariable = TRUE
    breaksw
  case yes:
    eval set $booleanvariable = TRUE
    breaksw
  case Yes:
    eval set $booleanvariable = TRUE
    breaksw
  case YES:
    eval set $booleanvariable = TRUE
    breaksw
  case false:
    eval set $booleanvariable = FALSE
    breaksw
  case False:
    eval set $booleanvariable = FALSE
    breaksw
  case FALSE:
    eval set $booleanvariable = FALSE
    breaksw
  case 0:
    eval set $booleanvariable = FALSE
    breaksw
  case no:
    eval set $booleanvariable = FALSE
    breaksw
  case No:
    eval set $booleanvariable = FALSE
    breaksw
  case NO:
    eval set $booleanvariable = FALSE
    breaksw
  default:
    echo "$0:t : boolean $booleanvariable=$val is not a boolean value. Use either '0,1,true,false,yes,no'"
    exit 1
  endsw
end

if ( $1 == "" ) then 
  echo "usage: $0:t [emuRDBname=MAUSOUTPUT][OUTZIP=<emuRDBname>.zip][validate=true][force=false][convsignal=true] <dir with *.wav and *.par/*_annot.json pairs>"
  echo "       $0:t createDBConfigOnly=<path+name> <dir with *.wav and *.par/*_annot.json pairs>" 
  echo "       The first call transforms MAUS generated BPFs (extension 'par') or emuR annot.json files + signals into emuR DB"
  echo "       named as given in emuRDBname (default: MAUSOUTPUT) plus '_emuDB'. The second call only writes the DBconfig.json file."
  echo "       If *.nis|nist|sph|mp4|mpg|mpeg are available instead of *.wav, these are transformed into *.wav for the emuDB,"
  echo "       option convsignal=true; other wise an ERROR is reported."
  echo "       If *_annot.json are available instead of *.par, these are used for the emuDB (copied)."
  echo "       If validate=1 the resulting *_annot.json/_DBconfig.json are validated using the validators in SCHEMAANNOT and SCHEMADBCONFIG"
  echo "       If force=true an existing output ZIP is overwritten"
  echo "       BPF files *must* have a SAM header entry. The following BPF tiers are recognized and converted:"
  echo "       $headlist $class1list $class4list"
  exit 1
endif

which uuid >& /dev/null
if ( $status != 0 ) then 
  echo "ERROR: ${0:t} : cannot find helper 'uuid' - exiting" > /dev/stderr
  exit 1
endif

set src = $1

if ( ! -d $src ) then 
  echo "ERROR: ${0:t} : cannot find input dir with *.wav|nis|nist|sph - *.par|annot.json pairs - exiting" > /dev/stderr
  exit 1
endif

# just to cover backward compatibilty for deprecated emuRtemplate option
if ( "$emuRtemplate" != "" ) set emuRDBname = `echo "${emuRtemplate:t}" | sed 's/^\([^_]*\)_.*$/\1/'`

# create temporary dir for target emuR DB
set DATE = `date '+%s'`
set TEMP = /tmp/$$_${DATE}_mausbpf2emuR
if ( -d $TEMP ) then 
  if ( `ls $TEMP/* | wc -l` > 0 ) then 
    rm -rf $TEMP/*
    if ( $status != 0 ) then 
      echo "ERROR: $0:t : cannot empty temporary dir $TEMP - exiting" > /dev/stderr
      exit 1
    endif
  else
    touch $TEMP/TMP
    rm -f $TEMP/TMP
    if ( $status != 0 ) then 
      echo "ERROR: $0:t : cannot write to temporary dir $TEMP - exiting" > /dev/stderr
      exit 1
    endif
  endif
else
  mkdir $TEMP
  if ( $status != 0 ) then 
    echo "ERROR: $0:t : cannot create  temporary dir $TEMP - exiting" > /dev/stderr
    exit 1
  endif
  chmod 777 $TEMP
endif

# check output
if ( $createDBConfigOnly == "" ) then 
  if ( $OUTZIP == "" ) set OUTZIP = ${emuRDBname}.zip
  if ( -e $OUTZIP ) then 
    if ( $force == "FALSE" ) then 
      echo "ERROR: $0:t : output zip file $OUTZIP already exists; use option 'force=true' to overwrite - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    else
      rm -f $OUTZIP
      if ( $status != 0 ) then 
        echo "ERROR: $0:t : cannot overwrite output zip $OUTZIP - exiting" > /dev/stderr
        rm -rf $TEMP
        exit 1
      endif
    endif
  endif
  touch $OUTZIP
  if ( $status != 0 ) then
    echo "ERROR: $0:t : cannot write to output zip $OUTZIP - exiting" > /dev/stderr
    rm -rf $TEMP
    exit 1
  endif
  rm -f $OUTZIP  # zip does not tolerate an existing empty zip file!
else
  if ( -e $createDBConfigOnly ) then 
    if ( $force == "TRUE" ) then 
      rm -f $createDBConfigOnly
      if ( $status != 0 ) then  
        echo "ERROR: $0:t : output file $createDBConfigOnly already exists and cannot delete - exiting" > /dev/stderr
        rm -rf $TEMP
        exit 1
      endif
    else
      echo "ERROR: $0:t : output file $createDBConfigOnly already exists; use force=true to overwrite - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
  else
    touch $createDBConfigOnly
    if ( $status != 0 ) then
      echo "ERROR: ${0:t} : cannot write to output file $createDBConfigOnly - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
  endif
endif

if ( $v > 0 ) echo "DEBUG: ${0:t} : transforming files in $src to emu DB ${emuRDBname} in ZIP $OUTZIP"

# Check inputs
ls $src/{*.wav,*.nis,*.nist,*.sph,*.mp4,*.mpg,*.mpeg} >& /dev/null
if ( $status != 0 ) then
  echo "ERROR: ${0:t} : no *.wav|nis|nist|sph|mp4|mpg|mpeg files found in source dir $src - exiting" > /dev/stderr
  rm -rf $TEMP 
  exit 1
endif

# If annotation inputs are BPF, check for required and optional BPF tiers in first BPF file
# WARNING: this script assumes that all input BPFs have the same structure!
set err_code = 0
set class4exist = ( ) 
set headexist = ( ) 
set class1exist = ( ) 
set class1existmult = ( )
ls "$src"/*.par >& /dev/null
if ( $status == 0 ) then

  # check for header entries
  set firstBPF = `ls "$src"/*.par | head -n 1`
  set headidx = 0
  foreach headkey ( $headlist )
    grep -q "^${headkey}:" $firstBPF
    if ( $status == 0 ) then 
      @ headidx ++
      set headexist = ( $headexist $headkey )
    endif 
  end
  if ( $headidx == 0 ) then 
    echo "ERROR: ${0:t} : input BPF has no header entry; minimal SAM is required - exiting" > /dev/stderr
    rm -rf $TEMP
    exit 1
  endif
  # check for plain and mult class 1 entries
  set class1idx = 0
  foreach class1key ( $class1list )
    grep -q "^${class1key}:" $firstBPF
    if ( $status == 0 ) then
      # plain class 1 tier
      @ class1idx ++
      set class1exist = ( $class1exist $class1key )
    endif 
  end
  set class1idxmult = 0
  foreach class1key ( $class1listmult )
    grep -q "^${class1key}:" $firstBPF
    # class 1 tier with word link list
    if ( $status == 0 ) then
      @ class1idxmult ++
      set class1existmult = ( $class1existmult $class1key )
    endif 
  end
  # check for class 4 entries
  set class4idx = 0
  foreach class4key ( $class4list )
    grep -q "^${class4key}:" $firstBPF
    if ( $status == 0 ) then 
      @ class4idx ++
      set class4exist = ( $class4exist $class4key )
    endif 
  end
  if ( $class1idx == 0 && $class4idx == 0 ) then
    echo "ERROR: $0:t : cannot find class1 nor class4 BPF tier in 1st BPF input (${firstBPF}) in $src - exiting" > /dev/stderr
    rm -rf $TEMP
    exit 1
  endif

else

  # no BPF input, check for emuDB annot.json
  ls "$src"/*_annot.json >& /dev/null
  if ( $status == 0 ) then
    set firstEMU = `ls "$src"/*_annot.json | head -n 1`
    # check for defined levels/attributes in firstEMU
    set headidx = 0
    foreach headkey ( $headlist )
      grep -q '"name": *"'"${headkey}"'"' "$firstEMU"
      if ( $status == 0 ) then 
        @ headidx ++
        set headexist = ( $headexist $headkey )
      endif 
    end
    if ( $headidx == 0 ) then 
      echo "ERROR: ${0:t} : input _annot.json $firstEMU has no header entry; minimal SAM is required - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
    # check for class 1 entries
    set class1idx = 0
    foreach class1key ( $class1list )
      grep -q '"name": *"'"${class1key}"'"' "$firstEMU"
       if ( $status == 0 ) then 
        @ class1idx ++
        set class1exist = ( $class1exist $class1key )
      endif 
    end
    # check for class 1 mult entries
    set class1idxmult = 0
    foreach class1key ( $class1listmult )
      grep -q '"name": *"'"${class1key}"'"' "$firstEMU"
       if ( $status == 0 ) then 
        @ class1idxmult ++
        set class1existmult = ( $class1existmult $class1key )
      endif 
    end
    # check for class 4 entries
    set class4idx = 0
    foreach class4key ( $class4list )
      grep -q '"name": *"'"${class4key}"'"' "$firstEMU"
      if ( $status == 0 ) then 
        @ class4idx ++
        set class4exist = ( $class4exist $class4key )
      endif 
    end
    if ( $class1idx == 0 && $class4idx == 0 ) then
      echo "ERROR: $0:t : cannot find class1 nor class4 BPF level/attribute in 1st _annot.json input (${firstEMU}) in $src - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
  else
    echo "ERROR: $0:t : cannot find BPF input (*.par) nor emuDB input (*_annot.json) in $src - exiting" > /dev/stderr
    rm -rf $TEMP
    exit 1
  endif 
endif

if ( $v > 0 ) echo "DEBUG: ${0:t} : detected tiers in input: $headexist $class1exist $class1existmult $class4exist"

# check for inconsistencies
if ( $class1idx == 0 && $class4idx == 0 ) then
  echo "ERROR: $0:t : input contains no class 1 nor a class 2 tier - exiting" > /dev/stderr
  rm -rf $TEMP
  exit 1
endif
if ( $class1idx == 0 ) then 
  if ( $v > 0 ) echo "DEBUG: ${0:t} : no class 1 tier (ITEM) detected in input: creating links from 'bundle' directly to class 4 tiers $class4exist"
  set class1level = ""
  if ( $class1idxmult > 0 ) then
    echo "ERROR: $0:t : found class 1 tier with multiple word links but no plain class 1 link as a reference - exiting"
    exit 1
  endif
else
  # default class 1 level (ITEM) is the first found in class1list (usually 'ORT' or 'KAN')
  set class1level = $class1exist[1]
  if ( $v > 0 ) echo "DEBUG: ${0:t} : select class 1 tier level name : $class1level"
endif
if ( $class4idx == 0 && $v > 0 ) echo "DEBUG: ${0:t} : no class 4 tier (SEGMENT) detected in input: creating a 'time-less' hierarchy"


# create emuR structure and DBconfig
set uuid = `uuid`
mkdir $TEMP/${emuRDBname}_emuDB
mkdir $TEMP/${emuRDBname}_emuDB/0000_ses

# DBconfig is made in three loops over headexist, class1exist and class4exist
if ( $v > 1 ) echo "DEBUG: ${0:t} : writing temporary DBConfig file in $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json"

# print preliminaries 
sed "s/##NAME##/${emuRDBname}/" <<EnD | sed "s/##UUID##/${uuid}/" >! $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
{
    "name": "##NAME##",
    "UUID": "##UUID##",
    "mediafileExtension": "wav",
    "ssffTrackDefinitions": [
    ],
    "levelDefinitions": [
        {
            "name": "bundle",
            "type": "ITEM",
            "attributeDefinitions": [
                {
                    "name": "bundle",
                    "type": "STRING"
                },
                {
                    "name": "source",
                    "type": "STRING"
                },
EnD

# header loop
set idx = 1
foreach key ( $headexist )
  printf '                {\n                    "name": "%s",\n                    "type": "STRING"\n                }' ${key}  >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  if ( $idx < $headidx ) echo "," >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  @ idx ++
end
printf "\n            ]\n        },\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json

# class 1 loop 
if ( $class1idx > 0 ) then 
  printf '        {\n            "name": "%s",\n            "type": "ITEM",\n            "attributeDefinitions": [\n' "$class1level" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  set idx = 1
  foreach key ( $class1exist ) 
    printf '                {\n                    "name": "%s",\n                    "type": "STRING"\n                }' ${key}  >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    if ( $idx < $class1idx ) then
      printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    else
      printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    endif
    @ idx ++
  end
  printf "            ]\n        }" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
endif 

# class 1 mult loop 
if ( $class1idxmult > 0 ) then 
  set idx = 1
  printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json   # mult is only possible with a class 1 before!
  foreach key ( $class1existmult ) 
    printf '        {\n            "name": "%s",\n            "type": "ITEM",\n            "attributeDefinitions": [\n' "$key" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    printf '                {\n                    "name": "%s",\n                    "type": "STRING"\n                }\n' ${key}  >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    printf "            ]\n        }" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    if ( $idx < $class1idxmult ) then
      printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    else
      printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    endif
    @ idx ++
  end
endif 

# class 4 loop 
if ( $class4idx > 0 ) then 
  set idx = 1
  if ( $class1idx > 0 ) printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  foreach key ( $class4exist ) 
    printf '        {\n            "name": "%s",\n            "type": "SEGMENT",\n            "attributeDefinitions": [\n' "$key" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    printf '                {\n                    "name": "%s",\n                    "type": "STRING"\n                }\n' ${key}  >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    printf "            ]\n        }" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    if ( $idx < $class4idx ) then
      printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    else
      printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    endif
    @ idx ++
  end
endif 

# end levelDefinitions
printf '    ],\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json

# linkDefinitions: depending of class1 existence link either bundle to class1 (and then class1 to class4), or bundle to class4
printf '    "linkDefinitions": [\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
if ( $class1idx == 0 ) then 
  # no class 1 level exists -> direct links from bundle to all class4 tiers
  # class 4 loop
  if ( $class4idx > 0 ) then
    set idx = 1
    foreach key ( $class4exist )
      printf '        {\n            "type": "ONE_TO_MANY",\n            "superlevelName": "bundle",\n            "sublevelName": "%s"\n        }' "${key}" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      if ( $idx < $class4idx ) then
        printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      else
        printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      endif
      @ idx ++
    end
  endif
else
  # class1 exists : links ifrom bundle to class1 and from class1 to class4
  printf '        {\n            "type": "ONE_TO_MANY",\n            "superlevelName": "bundle",\n            "sublevelName": "%s"\n        }' "${class1level}" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  # class 4 loop
  if ( $class4idx > 0 ) then
    printf ',\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    set idx = 1
    foreach key ( $class4exist )
      printf '        {\n            "type": "ONE_TO_MANY",\n            "superlevelName": "%s",\n            "sublevelName": "%s"\n        }' "${class1level}" "$key" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      if ( $idx < $class4idx ) then
        printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      else
        printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
      endif
      @ idx ++
    end
  else 
    printf '\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  endif
endif

if ( $class1idxmult > 0 ) then 
  # class1 mult tier(s) exist : links from bundle to class1 mult and from class1 mult to class1
  printf ',\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
  set idx = 1
  foreach key ( $class1existmult )
    printf '        {\n            "type": "ONE_TO_MANY",\n            "superlevelName": "bundle",\n            "sublevelName": "%s"\n        },' "${key}" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    printf '        {\n            "type": "ONE_TO_MANY",\n            "superlevelName": "%s",\n            "sublevelName": "%s"\n        }' "${key}" "${class1level}" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    if ( $idx < $class1idxmult ) then
      printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    else
      printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    endif
    @ idx ++
  end
endif

# end linkDefinitions
printf '    ],\n' >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json

# the rest DBConfig:
cat <<EnD >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    "EMUwebAppConfig": {
        "perspectives": [
            {
                "name": "default",
                "signalCanvases": {
                    "order": [
                        "OSCI",
                        "SPEC"
                    ],
                    "assign": [

                    ],
                    "contourLims": [

                    ]
                },
                "levelCanvases": {
                    "order": [
EnD
# class 4 loop
if ( $class4idx > 0 ) then
  set idx = 1
  foreach key ( $class4exist )
    printf '                        "%s"' "${key}" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    if ( $idx < $class4idx ) then
      printf ",\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    else
      printf "\n" >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
    endif
    @ idx ++
  end
endif
cat <<EnD >> $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json
                    ]
                },
                "twoDimCanvases": {
                    "order": [

                    ]
                }
            }
        ],
        "activeButtons": {
            "saveBundle": true,
            "showHierarchy": true
        }
    }
}
EnD

# validation
if ( $validate == "TRUE" ) then
  if ( $SCHEMADBCONFIG != "" ) then 
    if ( $v > 0 ) echo "DEBUG: ${0:t} : validating $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json using $SCHEMADBCONFIG"
    curl -s -H "Content-Type: applicationjson" --data-binary "@$TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json" "$SCHEMADBCONFIG" | grep -q 'SUCCESS'
    if ( $status != 0 ) then
      echo "ERROR: ${0:t} : _DBconfig.json does not validate or schema server not functional - exiting" > /dev/stderr
      echo "    $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json" > /dev/stderr
      curl -s -H "Content-Type: applicationjson" --data-binary "@$TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json" "$SCHEMADBCONFIG" > /dev/stderr
      rm -rf $TEMP
      exit 1
    else
      if ( $v > 0 ) echo "  -> Ok."
    endif
  else
    which jsonlint >& /dev/null
    if ( $status == 0 ) then
      if ( $v > 0 ) echo "DEBUG: ${0:t} : validating $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json using jsonlint"
      jsonlint "$TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json"
      if ( $status != 0 ) then
        echo "ERROR: ${0:t} : _DBconfig.json does not validate syntactially - exiting" > /dev/stderr
        echo "    $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json" > /dev/stderr
        rm -rf $TEMP
        exit 1
      else
        if ( $v > 0 ) echo "  -> Ok."
      endif
    else
      echo "WARNING: $0:t : cannot validate _DBConf.json because neither jsonlint nor a schema validator are functional" > /dev/stderr
    endif
  endif
endif

# create only DBconfig.json file output
if ( $createDBConfigOnly != "" ) then
  cp $TEMP/${emuRDBname}_emuDB/${emuRDBname}_DBconfig.json $createDBConfigOnly
  if ( $status != 0 ) then
    echo "ERROR: $0:t : cannot write to output file $createDBConfigOnly - exiting" > /dev/stderr
    rm -rf $TEMP
    exit 1
  endif
  if ( $v > 0 ) echo "DEBUG: ${0:t} : writing _DBconfig.json to $createDBConfigOnly"
  rm -rf $TEMP
  exit 0
endif

# go over all signals in $src, locate corresponding *.par and convert into
# *_annot.json or find corresponding *_annot.json,
# create bundle dir in output emuR structure, convert non-wav signal to wav,
# copy *_annot.json and and *.wav to bundle dir
foreach pf ( $src/{*.wav,*.nis,*.nist,*.sph,*.mp4,*.mpg,*.mpeg} )
  if ( $v > 0 ) echo "DEBUG: ${0:t} : processing signal $pf"

  # make the bundle dir
  mkdir $TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl

  # if signal is not *.wav, try to transform 
  if ( ${pf:e} != "wav" ) then 
    if ( $convsignal == "FALSE" ) then 
      echo "ERROR: $0:t : input signal ${pf:t} is not RIFF WAVE (extension 'wav') - exiting" > /dev/stderr
      echo "     set option convsignal=true to automatically convert nis|nist|sph|mp4|mpg|mpeg" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
    switch ( ${pf:e} )
    case "nis":
    case "nist":
    case "sph":
      which sox >& /dev/null
      if ( $status != 0 ) then
        echo "ERROR: $0:t : sox is not installed, cannot convert input signals (*.${pf:e}) to *.wav - exiting" > /dev/stderr
        rm -rf $TEMP 
        exit 1
      endif
      sox -t 'sph' $pf $TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl/${pf:t:r}.wav
      if ( $status != 0 ) then
        echo "ERROR: $0:t : sox reported error while converting ${pf:t} to  *.wav - exiting" > /dev/stderr
        rm -rf $TEMP
        exit 1
      endif
      breaksw
    case "mp4":
    case "mpg":
    case "mpeg":
      which ffmpeg >& /dev/null
      if ( $status != 0 ) then
        echo "ERROR: $0:t : ffmpeg is not installed, cannot convert input signals (*.${pf:e}) to *.wav - exiting" > /dev/stderr
        rm -rf $TEMP
        exit 1
      endif
      set VIDEOSAMPLERATE = `ffprobe ${pf} |& grep 'Stream .* Audio' | head -n 1 | sed 's/^.* \([0-9][0-9]*\) Hz.*$/\1/'`
      if ( $status != 0 || $VIDEOSAMPLERATE == "" ) then 
        echo "WARNING: ${0:t} : ffprobe cannot determine audio sample rate from input video; using 16000Hz" > /dev/stderr
        echo "                  this means that e.g. BPF results are based on 16000Hz sampling rate" > /dev/stderr
        set VIDEOSAMPLERATE = 16000
      else
        echo "WARNING: ${0:t} : extracting audiotrack with ${VIDEOSAMPLERATE}Hz sampling rate from video input" > /dev/stderr
      endif
      # we assume that '-ac 1' equals the default soundtrack (until now this always has been true)
      ffmpeg -loglevel quiet -y -i ${pf} -acodec pcm_s16le -ac 1 -ar $VIDEOSAMPLERATE $TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl/${pf:t:r}.wav
      if ( $status != 0 ) then
        echo "ERROR: $0:t : sox reported error while converting ${pf:t} to  *.wav - exiting" > /dev/stderr
        rm -rf $TEMP
        exit 1
      endif
      breaksw
    default:
      breaksw
    endsw
  else
    cp ${pf:r}.wav $TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl
  endif

  # checking which files exist
  set bpfExists = FALSE
  set jsonExists = FALSE
  if ( -e ${pf:r}.par ) then 
    set bpfExists = TRUE
    if ( $v > 0 ) echo "DEBUG: ${0:t} : found BPF input ${pf:r}.par"
  endif 
  if ( -e ${pf:r}_annot.json ) then
    set jsonExists = TRUE
    if ( $v > 0 ) echo "DEBUG: ${0:t} : found JSON input ${pf:r}_annot.json"
  endif 

  if ( $bpfExists == TRUE && $jsonExists == TRUE ) then
    echo "WARNING: $0:t : both the json and the par file exist, will use the json file and ignore the information in the par file" > /dev/stderr
  endif

  if (  $bpfExists == FALSE && $jsonExists == FALSE ) then 
    echo "WARNING: $0:t : can neither find bpf file ${pf:r}.par nor annot.json file ${pf:r}_annot.json for signal file ${pf} - skipping" > /dev/stderr
    continue
  endif

  # if no _annot.json file exists, create one otherwise use the existing one
  if ( $jsonExists == FALSE ) then
    $SOURCE/mausbpf2emuR v=$v OUTDIR=$TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl validate=$validate SCHEMA=$SCHEMAANNOT ${pf:r}.par
    if ( $status != 0 ) then 
      echo "ERROR: $0:t : converter mausbpf2emuR returns error - exiting" > /dev/stderr
      rm -rf $TEMP
      exit 1
    endif
  else
    cp ${pf:r}_annot.json $TEMP/${emuRDBname}_emuDB/0000_ses/${pf:t:r}_bndl
  endif

end

# pack emuR structure in result ZIP
if ( $v > 0 ) echo "DEBUG: ${0:t} : creating ZIP $OUTZIP"
set PWD = `pwd`
cd $TEMP
zip -qr ${OUTZIP:t} ${emuRDBname}_emuDB
cd $PWD
mv $TEMP/${OUTZIP:t} $OUTZIP

rm -rf $TEMP

exit 0

