# internal shortcut entry point
repl() {
  rlx.commands.repl "$@";
}

# main
rlx.commands.repl() {
  if [ -z "${info[server]:-}" ]; then
    console error -- "no server selected";
  elif [ -z "${info[database]:-}" ]; then
    console error -- "no database selected";
  else
    if [ $# -eq 0 ]; then
      console error -- "no replicate command specified";
    else
      # find out the database name used for replication 
      config get replicator db false;
      if ! ${flags[success]}; then
        console error -- "could not fetch replication database name";
        return 1;
      fi
      local repldb="${info[config]:-}";
      # check the database exists
      db head "${repldb}";
      if ! ${flags[success]}; then
        console error -- "replication database %s does not exist" "${repldb}";
        return 1;
      fi
      local create_target=true;
      local continuous=false;
      local source="${info[server]}/${info[database]}";
      local repl_namespace="repl.commands";
      local cmd="${1:-}";
      shift;
      if ! method.exists? "${repl_namespace}.${cmd}"; then
        local file="${cmd}";
        tilde.expand;
        if [ -f "${file}" ]; then
          repl.commands.send "${file}" "$@";
        else
          console error -- "%s does not exist" "${file}";
        fi
      else
        delegate "${repl_namespace}" "${cmd}" "$@";
      fi
    fi
  fi
}

repl.commands.db() {
  printf "${repldb}\n";
}

# add a replication document
repl.commands.add() {
  local id="${1:-}";
  local target="${2:-}";
  local template="${3:-${rlx_settings[tplrepl]:-repl}}";
  local params=( ${@:4} );
  if repl.validate; then
    tpl clean;
    repl.show;
  fi
}

repl.commands.restart() {
  local id="${1:-}";
  if [ -z "${id}" ]; then
    console error -- "no replication id specified";
  else
    local print=false;
    repl.commands.get "${id}";
    if ${flags[success]}; then
      local json=$( cat "${files[response]}" );
      local force=true;
      flags[success]=false;
      repl.commands.rm "${id}";
      if ${flags[success]}; then
        tpl clean;
        tpl parse repl-restart false \
          "doc=${json}";
        rlx.run couchdb.doc.save "${info[server]}" "${repldb}" \
          "${files[input]}" "${id}";
        if ${flags[success]}; then
          console ok -- "saved replication %s" "${id}";
        fi
      fi
    fi
  fi
}

# add a filtered replication document
repl.commands.filter() {
  repl.commands.add \
    "${2:-}" "${3:-}" \
    "${rlx_settings[tplreplfilter]:-repl-filter}" \
    "filter=${1:-}";
}

# replicate specific document ids
repl.commands.docs() {
  local id="${1:-}"; shift;
  local target="${1:-}"; shift;
  local template="${rlx_settings[tplrepldocs]:-repl-docs}";
  if repl.validate; then
    tpl clean;
    tpl array doc_ids "$@";
    repl.show;
  fi
}

repl.commands.ls() {
  doc ls "${repldb}";
}

repl.commands.rm() {
  local id="${1:-}";
  if [ -z "${id}" ]; then
    console error -- "no document id specified";
  else
    doc rm "${id}" "${repldb}";
  fi
}

repl.commands.get() {
  local id="${1:-}";
  local rev="${2:-}";
  if [ -z "${id}" ]; then
    console error -- "no document id specified";
  else
    db context "${repldb}" doc get "${id}" "${rev}";
  fi
}

repl.commands.edit() {
  local id="${1:-}";
  if [ -z "${id}" ]; then
    console error -- "no document id specified";
  else
    doc edit "${id}" "" "${repldb}";
  fi
}

## PRIVATE

repl.validate() {
  if [ -z "${id}" ]; then
    console error -- "no replication id specified";
  elif [ -z "${target}" ]; then
    console error -- "no replication target specified";
  elif [[ "${target}" =~ ${regexp[alias]} ]]; then
    alias.expand "${target}" target true || return 1;
    return 0;
  else
    return 0;
  fi
  return 1;
}

repl.show() {
  if [ "${source}" == "${target}" ]; then
    console error -- "cannot replicate, source %s equals target %s" \
      "${source}" "${target}";
    return 1;
  fi
  tpl parse "${template}" false \
    "id=${id}" \
    "source=${source}" \
    "target=${target}" \
    "continuous=${continuous}" \
    "create_target=${create_target}" \
    "${params[@]:-}" \
    || return 1;
  saved() {
    rlx.run couchdb.doc.save \
      "${info[server]}" "${repldb}" \
      "${files[document]}" "${id}";
    if ${flags[success]}; then
      rlx.json.print;
    fi
  }
  rlx.edit "${files[input]}";
}
