#!/bin/sh -e
#
# 2018 Steven Armstrong (steven-cdist at armstrong.cc)
# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch)
#
# This file is part of cdist.
#
# cdist is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cdist is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
#

if [ -f "$__object/parameter/before" ] && [ -f "$__object/parameter/after" ]; then
   echo "Use either --before OR --after but not both." >&2
   exit 1
fi

if [ -f "$__object/parameter/file" ]; then
   file="$(cat "$__object/parameter/file")"
else
   file="/$__object_id"
fi

state_should="$(cat "$__object/parameter/state")"
state_is="$(cat "$__object/explorer/state")"

if [ -z "$state_is" ]; then
   printf 'The file "%s" is missing. Please create it before using %s on it.\n' "$file" "${__type##*/}" >&2
   exit 1
fi

if [ "$state_should" = "$state_is" ] || \
	{ [ "$state_should" = "present" ] && [ "$state_is" = "matching" ] ;} || \
	{ [ "$state_should" = "replace" ] && [ "$state_is" = "present" ] ;} ; then
   # If state matches already, or 'present' is used and regex matches
   # or 'replace' is used and the exact line is present, then there is
   # nothing to do
   exit 0
fi

if [ -f "$__object/parameter/before" ]; then
   position="before"
elif [ -f "$__object/parameter/after" ]; then
   position="after"
else
   # By default we append to the end of the file.
   position="end"
fi

if [ -f "$__object/parameter/regex" ]; then
   needle="regex"
else
   needle="line"
fi

add=0
remove=0
case "$state_should" in
   present|replace)
      if [ "$state_is" = "wrongposition" ] || [ "$state_is" = "matching" ]; then
         echo updated >> "$__messages_out"
         remove=1
      else
         echo added >> "$__messages_out"
      fi
      add=1
   ;;
   absent)
      echo removed >> "$__messages_out"
      remove=1
   ;;
esac

cat << DONE
tmpfile=\$(mktemp ${file}.cdist.XXXXXXXXXX)
# preserve ownership and permissions of existing file
if [ -f "$file" ]; then
   cp -p "$file" "\$tmpfile"
fi

awk -v position="$position" -v needle="$needle" -v remove=$remove -v add=$add '
function _find(_text, _pattern) {
   if (needle == "regex") {
      return match(_text, _pattern)
   } else {
      return index(_text, _pattern)
   }
}
BEGIN {
   line_file = ENVIRON["__object"] "/parameter/line"
   getline line < line_file
   # Need to close line file as it may be re-read as pattern below.
   close(line_file)
   getline pattern < (ENVIRON["__object"] "/parameter/" needle)
   getline anchor < (ENVIRON["__object"] "/parameter/" position)
}
{
   if (remove) {
      if (_find(\$0, pattern)) {
         # skip over this line -> remove it
         next
      }
   }
   if (add) {
      if (anchor && match(\$0, anchor)) {
         if (position == "before") {
            print line
            add = 0
            print
         } else if (position == "after") {
            print
            print line
            add = 0
         }
         next
      }
   }
   print
}
END {
   if (add) {
      print line
   }
}
' "$file" > "\$tmpfile"
mv -f "\$tmpfile" "$file"
DONE

if [ -f "$__object/parameter/onchange" ]; then
   cat "$__object/parameter/onchange"
fi
