# alias for internal use
tpl() {
  rlx.commands.tpl "$@";
}

# template commands
rlx.commands.tpl() {
  local tplprefix="tpl_";
  local lang="${rlx_settings[templatelang]:-${rlx_settings[lang]:-}}";
  local extension="${extensions[${lang:-}]:-}";
  local interpreter=cat;
  if [ "${lang}" != false ]; then
    rlx.interpreter template interpreter "${lang}";
    if [ ! -x "${interpreter}" ]; then
      console error -- "no template interpreter %s for language %s" \
        "${interpreter}" "${lang}";
      return 1;
    fi
  fi
  local paths=();
  if [ -d "${rlx_settings[templates]:-}" ]; then
    paths+=( "${rlx_settings[templates]:-}" );
  fi
  paths+=( "${defaults[template]:-}" );
  local namespace="tpl.commands";
  local cmd="${1:-}";
  shift;
  if ! method.exists? "${namespace}.${cmd}"; then
    console error -- "unknown tpl command %s" "${cmd}";
  else
    delegate "${namespace}" "${cmd}" "$@";
  fi
}

# print template variables
tpl.commands.get() {
  local k v;
  while [ -n "${1:-}" ];
    do
      k="${tplprefix}${1:-}";
      variable.get "${k}" v \
        && console print -- "${k}=%s" "${v}";
      shift;
  done
}

# set template variables
tpl.commands.set() {
  local print=${print:-true};
  if [ "${1:-}" == true ] || [ "${1:-}" == false ]; then
    print="${1:-}"; shift;
  fi
  declare -A vars;
  local k v parts;
  while [ -n "${1:-}" ];
    do
      k="${1:-}"; shift;
      local IFS="=";
      parts=( $k ); unset IFS;
      k="${parts[0]:-}";
      v="${parts[1]:-}";
      if [ -z "${k}" ]; then
        console error -- "no variable key specified";
        return 0;
      elif [ -z "${v}" ]; then
        console error -- "no variable value specified for %s" "${k}";
        return 0;
      elif [[ "${k}" =~ $variable_name_sanitize_regexp ]]; then
        console error -- "invalid variable name %s" "${k}";
        return 0;
      fi
      k="${tplprefix}${k}";
      vars[$k]="${v}";
  done
  tpl.assign $print;
}

# find a template file by identifier
tpl.commands.find() {
  local id="${1:-}";
  local name="${lang}/${id}.${extension}";
  if [ -z "${id}" ]; then
    console error -- "no template identifier specified";
  else
    #local file;
    for file in "${paths[@]}"
      do
        file="${file%/}";
        file="${file}/${name}";
        if [ -f "${file}" ]; then
          #printf "%s\n" "${file}";
          return 0;
        fi
    done
    console error -- "no template found for %s" "${id}";
  fi
  return 1;
}

# set an array of variables
tpl.commands.array() {
  local key="${1:-}"; shift;
  local elements=( $@ );
  if [ ${#elements[@]} -gt 0 ]; then
    local i length=$#;
    tpl set false "${key}_length=${length}";
    for((i=0;i < $length;i++))
      do
        tpl set false "${key}_${i}=${elements[$i]}";
    done
  fi
}

tpl.commands.compact() {
  local tabstops="${rlx_settings[tabstops]:-0}";
  #settings set tabstops 0;
  export JSON_INDENT=0;
  tpl parse $@;
  #settings set tabstops "${tabstops}";
}

# parse and print a template
tpl.commands.parse() {
  local id="${1:-}"; shift;
  #echo "parse got template $id"
  local print=true;
  local plain=false;
  if [ "${1:-}" == true ] || [ "${1:-}" == false ]; then
    print="${1:-}"; shift;
  fi
  if [ "${1:-}" == true ] || [ "${1:-}" == false ]; then
    plain="${1:-}"; shift;
  fi
  if [ -z "${id}" ]; then
    console error -- "no template identifier specified";
  else
    if [ $# -gt 0 ]; then
      tpl set false "$@" || return 1;
    fi
    if [ "${lang}" != false ]; then
      local file;
      tpl find "${id}" \
        || return 1;
    else
      # no template in use
      file="${defaults[object]}";
      interpreter=echo;
    fi
    export JSON_INDENT="${rlx_settings[tabstops]:-}";
    rlx.debug "parse %s using %s" "${file}" "${lang}";
    rlx.debug "template parser %s (print=%s,indent=%s)" \
      "${interpreter}" "${print}" "${JSON_INDENT}";
    ${interpreter} ${file} >| "${files[input]}" \
      || console error -- "template parsing failed";
    if [ ! -f "${files[input]}" ]; then
      console error -- "missing template output %s" "${files[input]}";
      return 1;
    fi
    if $print; then
      if $plain; then
        #echo "printing parsed template..."
        cat "${files[input]}";
      else
        rlx.json.print "${files[input]}";
      fi
    fi
  fi
}

# print all template variables
tpl.commands.print() {
  local k v;
  for k in ${!tpl_*};
    do
      variable.get "${k}" v;
      console print -- "${k}=%s" "${v}";
  done
}

# remove all template environment variables
tpl.commands.clean() {
  unset ${!tpl_*};
}

# copy system templates to a user directory
tpl.commands.copy() {
  local file="${1:-}";
  file="${file%/}";
  tilde.expand;
  local name="${2:-${defaults[usertemplates]}}";
  if [ ! -d "${file}" ]; then
    console error -- "%s is not a directory" "${file}";
  else
    local path="${file}/${name}";
    if [ -e "${path}" ]; then
      console error -- "cannot copy, %s exists" "${path}";
    else
      mkdir -p "${path}" \
        || {
        console error -- "could not create %s" "${path}";
        return 1;
      }
      local sd;
      for sd in "${directories[template]}"/*
        do
          cp -R "${sd}" "${path}" \
            || {
            console error -- "could not copy %s to %s" "${sd}" "${path}";
            return 1;
          }
      done
      console info -- "templates copied to %s" "${path}";
      settings set templates "${path}";
      console info -- \
        "run %s to set the new templates directory as the default" \
        "settings save";
    fi
  fi
}

## PRIVATE

tpl.assign() {
  local print="${1:-true}";
  local k v;
  for k in "${!vars[@]}";
    do
      v="${vars[$k]}";
      export $k="$v";
      $print && console print -- "${k}=%s" "${v}" || true;
  done
}

