#!/bin/bash

# in those arrays, each line is:
#   <file> <sha1sum of file (without line 4 which changes depending on the location of the files)> <patch to apply to file>

RRC_Rel10=(
  "SystemInformation-r8-IEs.h" 603cd6615cff36ec7020692d72c0d6de7c4859cb "fix_asn1.data/RRC.rel10/SystemInformation-r8-IEs.h.diff"
)

X2AP_Rel11_2=(
  "X2ap-CriticalityDiagnostics-IE-List.h" ae96308b37fcbcbf39da5012e42968135fc5f27b "fix_asn1.data/X2AP.rel11.2/X2ap-CriticalityDiagnostics-IE-List.h.diff"
  "NativeInteger.c"                       1a55f5402fd363318cf5444ffe1f67530dcf66ff "fix_asn1.data/X2AP.rel11.2/NativeInteger.c.diff"
  "constr_SET_OF.c"                       808cbbdf19b118c0bdb04e3acf2cbe6e4133be2b "fix_asn1.data/X2AP.rel11.2/constr_SET_OF.c.diff"
)

S1AP_Rel10_5=(
  "NativeInteger.c" 1a55f5402fd363318cf5444ffe1f67530dcf66ff "fix_asn1.data/S1AP.rel10.5/NativeInteger.c.diff"
  "constr_SET_OF.c" 808cbbdf19b118c0bdb04e3acf2cbe6e4133be2b "fix_asn1.data/S1AP.rel10.5/constr_SET_OF.c.diff"
)

red_color="$(tput setaf 1)"
green_color="$(tput setaf 2)"
reset_color="$(tput sgr0)"

function error()
{
  echo -e "$red_color"ERROR: "$@""$reset_color"
  exit 1
}

function check_sha1()
{
  local file="$1"
  local target_sha1="$2"

  if [ ! -f "$file" ]
  then
    error "$file: no such file"
  fi

  # we don't use the line 4 of the file
  # it contains the location of the ASN1 grammar
  # and this location is not the same on every
  # installation (this is for *.h files, for *.c
  # files it's no big deal to skip that line)
  local computed_sha1=$(sed 4d "$file" | sha1sum | cut -f 1 -d ' ')

  if [ "$target_sha1" != "$computed_sha1" ]
  then
    error "$file: wrong SHA1"
  fi
}

function patch_file()
{
  local patch="$1"
  local file="$2"

  echo -e "$green_color""patch file $file with $OPENAIR_DIR/cmake_targets/tools/$patch""$reset_color"

  patch "$file" "$OPENAIR_DIR/cmake_targets/tools/$patch"
  if [ $? -ne 0 ]
  then
    error "patching of $file with $OPENAIR_DIR/cmake_targets/tools/$patch failed"
  fi
}

function apply_patches()
{
  local directory="$1"
  local array=$2
  local len=$3       # the length could be computed locally but the way to do it is not clear to me [CROUX]

  local i
  local file
  local sha1
  local patch
  local item

  for (( i = 0; i < $len; i += 3 ))
  do
    # special bash syntax to access the array
    item=$array[$i];       file=${!item}
    item=$array[$((i+1))]; sha1=${!item}
    item=$array[$((i+2))]; patch=${!item}
    check_sha1 "$directory/$file" "$sha1"
    patch_file "$patch" "$directory/$file"
  done
}

function patch_rrc()
{
  local directory="$1"
  local version="$2"

  case "$version" in
    Rel10 )
      echo "patching RRC files release 10"
      apply_patches "$directory" RRC_Rel10 ${#RRC_Rel10[*]}
      ;;
    Rel8 )
      echo "patching RRC files release 8 TODO?"
      ;;
    * )
      error unknwon/unhandled RRC version \'"$version"\'
      ;;
  esac
}

function patch_x2ap()
{
  local directory="$1"
  local version="$2"

  case "$version" in
    R11 )
      echo "patching X2AP files release 11.2"
      apply_patches "$directory" X2AP_Rel11_2 ${#X2AP_Rel11_2[*]}
      ;;
    * )
      error unknwon/unhandled X2AP version \'"$version"\'
      ;;
  esac
}

function patch_s1ap()
{
  local directory="$1"
  local version="$2"

  case "$version" in
    R10 )
      echo "patching S1AP files release 10.5"
      apply_patches "$directory" S1AP_Rel10_5 ${#S1AP_Rel10_5[*]}
      ;;
    * )
      error unknwon/unhandled S1AP version \'"$version"\'
      ;;
  esac
}

function main()
{
  if [ $# -ne 3 ]
  then
    echo "ERROR: pass <output directory> <module> <version>"
    exit 1
  fi

  if [ x"$OPENAIR_DIR" = x ]
  then
    error "the variable OPENAIR_DIR is not set"
  fi

  local directory="$1"
  local module="$2"
  local version="$3"

  case "$module" in
    RRC )
      patch_rrc "$directory" "$version"
      ;;
    X2AP )
      patch_x2ap "$directory" "$version"
      ;;
    S1AP )
      patch_s1ap "$directory" "$version"
      ;;
    * )
      error unknown module "$module"
      ;;
  esac

  exit 0
}

main "$@"
