#!/bin/sh -efu

. bacula-sh-functions
. shell-var
. shell-quote

bacula_client_template_dir="/etc/alterator/bacula/templates"
qbacula_client_template_dir=
quote_sed_regexp_variable qbacula_client_template_dir "$bacula_client_template_dir"

__client_prefix="client-"

__client_fileset()
{
    local name="$1";shift
    local template="$1";shift
    local filelist_dir="$bacula_filelist_dir/$name"

    __director_include_add "$bacula_fileset_dir/$name.conf"<<EOF
$bacula_magic_string
FileSet {
  Name = "$name"
  Include {
    Options {
      signature = MD5
    }
    File="<$filelist_dir/include"
  }

  Exclude {
    File="<$filelist_dir/exclude"
  }
}
EOF

    local template_include_file="$bacula_client_template_dir/$template/include-list"
    local template_exclude_file="$bacula_client_template_dir/$template/exclude-list"

    mkdir -p -- "$filelist_dir"
    if [ -f "$template_include_file" ];then
	cp -f -- "$template_include_file" "$filelist_dir/include"
    else
	touch "$filelist_dir/include"
    fi

    if [ -f "$template_exclude_file" ];then
	cp -f -- "$template_exclude_file" "$filelist_dir/exclude"
    else
	touch "$filelist_dir/exclude"
    fi
}

# create initial client settings
# usage: bacula_client_add <name> <template>
bacula_client_add()
{
    local name="$__client_prefix$1" #use prefix to avoid conflicts with strange default names
    local template="$2"
    # client object definition
    __director_include_add "$bacula_client_dir/$name.conf"<<EOF
Client {
  Name = "$name"
  Address = 127.0.0.1
  FDPort = 9102
  Password = ""
  Catalog = "$bacula_catalog_name"
  File Retention = 30 days
  Job Retention = 6 months
  AutoPrune = yes
}
EOF

    # client fileset definition
    __client_fileset "$name" "$template"

    # client schedule definition
    bacula_schedule_set_time "$bacula_schedule_dir/$name.conf" "$name" "23:00:00"

    # client pool definition
    bacula_pool_add "$name"

    # client job definition
    __director_include_add "$bacula_job_dir/$name.conf"<<EOF
Job {
  Name = "$name"
  JobDefs = "$bacula_default_job_name"
  Client = "$name"
  FileSet = "$name"
  Schedule = "$name"
  Pool = "$name"
  Write Bootstrap = "$bacula_localstate_dir/$name.bsr"
  Enabled = Yes
}
EOF
    # client fd template
    template_fd_file="$bacula_client_template_dir/$template/bacula-fd.conf.in"
    [ ! -s "$template_fd_file" ] ||
	cp -f -- "$template_fd_file" "$bacula_client_dir/$name-fd.conf.in"
}

# create remove client settings
# usage: bacula_client_del <name> <storage-dir>
bacula_client_del()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local volume_dir="$1";shift

    bacula_job_cancel "$name" # try to stop all active client's jobs
    bacula_pool_del "$name" "$volume_dir" #client pool
    bacula_job_del_by_name "$name" #remove also broken client jobs

    __director_include_del "$bacula_schedule_dir/$name.conf" #client schedule
    __director_include_del "$bacula_job_dir/$name.conf" #client job

    __director_include_del "$bacula_fileset_dir/$name.conf" #client fileset
    rm -rf -- "$bacula_filelist_dir/$name" #client filelist
    __director_include_del "$bacula_client_dir/$name.conf" #client object
    rm -f -- "$bacula_client_dir/$name-fd.conf.in" # client fd template
}

# clear client's job
# usage: bacula_client_del <name> <storage-dir>
bacula_client_clear()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local volume_dir="$1";shift

    # try to stop all active client's jobs
    bacula_job_cancel "$name"

    #FIXME: wait until jobs are really canceled, otherwize we will have not purged volume

    # clear disk space and client's pool
    bacula_pool_clear "$name" "$volume_dir"

    # also remove rest of client jobs (broken jobs not cleared by pool clear procedure)
    bacula_job_del_by_name "$name"
}

# check for client existance
# note: this is a very simple algo, it doesn't cover all possible cases
# usage: bacula_client_exists <name>
bacula_client_exists()
{
    local name="$__client_prefix$1" #use prefix to avoid conflicts with strange default names

    [ -s "$bacula_client_dir/$name.conf" ]
}

bacula_client_get_address()
{
    local name="$__client_prefix$1" #use prefix to avoid conflicts with strange default names

    bacula_config_get "$bacula_client_dir/$name.conf" Client Address
}

bacula_client_set_address()
{
    local name="$__client_prefix$1";shift  #use prefix to avoid conflicts with strange default names
    local value="$1";shift

    bacula_config_set "$bacula_client_dir/$name.conf" Client Address "$value"
}

bacula_client_get_password()
{
    local name="$__client_prefix$1";shift  #use prefix to avoid conflicts with strange default names
    local value="$1";shift

    bacula_config_get "$bacula_client_dir/$name.conf" Client Password
}

bacula_client_set_password()
{
    local name="$__client_prefix$1";shift  #use prefix to avoid conflicts with strange default names
    local value="$1";shift

    bacula_config_set "$bacula_client_dir/$name.conf" Client Password "$value"
}


bacula_client_get_port()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names

    bacula_config_get "$bacula_client_dir/$name.conf" Client FDPort
}

bacula_client_set_port()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local value="$1";shift

    bacula_config_set "$bacula_client_dir/$name.conf" Client FDPort "$value"
}

# get client's schedule start time
# usage: bacula_client_get_time <name>
bacula_client_get_time()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names

    bacula_schedule_get_time "$bacula_schedule_dir/$name.conf"
}

# set client's schedule start time
# usage: bacula_client_get_time <name> <time>
bacula_client_set_time()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local time="$1";shift

    bacula_schedule_set_time "$bacula_schedule_dir/$name.conf" "$name" "$time"
}

# get client's scheduling status
# usage: bacula_client_schedule_status <name>
bacula_client_get_schedule()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names

    if shell_var_is_yes "$(bacula_config_get "$bacula_job_dir/$name.conf" Job Enabled)";then
	echo "daily"
    else
	echo "off"
    fi
}

# edit client's scheduling
# usage: bacula_client_schedule_on <name> <value>
bacula_client_set_schedule()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local value="$1";shift

    case "$value" in
	daily)
	    bacula_job_enable "$name"
	    bacula_config_set "$bacula_job_dir/$name.conf" Job Enabled Yes
	    ;;
	off)
	    bacula_job_disable "$name"
	    bacula_config_set "$bacula_job_dir/$name.conf" Job Enabled No
	    ;;
    esac
}

# read client's volume retention
# usage: bacula_client_get_retention <name>
bacula_client_get_retention()
{
    bacula_pool_get_retention "$bacula_pool_dir/$__client_prefix${1}.conf"
}

# update client's volume retention
# usage: bacula_client_set_retention <name> <value>
bacula_client_set_retention()
{
    bacula_pool_set_retention "$bacula_pool_dir/$__client_prefix${1}.conf" "$2"
}

# list available clients
# note: don't use 'list clients' console command because it's doesn't show actual results immediately
bacula_client_list()
{
    local f v
    find "$bacula_client_dir" -type f -name '*.conf'|
	while read f;do
	    v="$(bacula_config_get "$f" Client Name)"
	    [ "$v" != "$bacula_local_client_name" ] || continue
	    echo "${v#$__client_prefix}" #remove prefix
	done
}

bacula_client_filelist_path()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names
    local type="$1";shift
    printf '%s/%s/%s\n' "$bacula_filelist_dir" "$name" "$type"
}

bacula_client_backup_run()
{
    local name="$__client_prefix$1";shift #use prefix to avoid conflicts with strange default names

    bacula_job_run "$name" >&2
    bacula_job_run "$bacula_catalog_job_name" >&2
}

# read status of last job with specified name
bacula_client_backup_last_status()
{
    bacula_console_query_sql "select  jobStatus from Job where Name='$__client_prefix$1' order by StartTime desc limit 1;"
}

bacula_client_backup_count()
{
    bacula_console_query_sql "select count(jobId) from Job where Name='$__client_prefix$1' and jobStatus!='C';"
}

# read in one query main backup summary data
bacula_client_backup_summary()
{
    bacula_console_query_sql "select min(StartTime),max(startTime),sum(jobBytes) from Job where Name='$__client_prefix$1' and jobStatus!='C';"
}

bacula_client_schedule_list()
{
    local f
    find "$bacula_schedule_dir" -type f -name '*.conf'|
	while read f ;do
	    local name="$(bacula_config_get "$f" Schedule Name)"
	    local real_name="${name#client-*}"

	    [ "$name" != "$real_name" ] || continue
	    shell_var_is_yes "$(bacula_config_get "$bacula_job_dir/$name.conf" Job Enabled)" || continue

	    printf '%s\t%s\n' "$(bacula_schedule_get_time "$f")" "$real_name"
	done|
	sort -n -k1,1
}

# restore file or directory for specified client
bacula_client_restore_file()
{
    local name="$__client_prefix$1";shift
    local date="$1";shift
    local file="$1";shift
    local restoreclient="$__client_prefix$1";shift
    local restorepath="$1";shift

    bacula_restore_file "$name" "$name" "$date" "$file" "$restoreclient" "$restorepath"
}

# current file progress
bacula_client_get_progress()
{
    bacula_file_get_progress "$__client_prefix$1"
}

# available templates
bacula_client_template_list()
{
    find "$bacula_client_template_dir" -name '.desktop'|
    xargs alterator-dump-desktop \
		-v lang="$in_language" \
		-v out="Filename;Name"|
	  sed "s/$qbacula_client_template_dir\/\([^/]\+\)\/.desktop\([[:space:]]\+\)/\1\2/"
}

bacula_client_template_fd()
{
    local name="$1";shift
    local director="$(bacula_director_get_name)"
    local password="$(bacula_client_get_password "$name")"

    local qname qdirector qpassword
    quote_sed_regexp_variable qname "$name"
    quote_sed_regexp_variable qdirector "$director"
    quote_sed_regexp_variable qpassword "$password"

    local fname="$__client_prefix$name" #use prefix to avoid conflicts with strange default names
    local fd_file="$bacula_client_dir/$fname-fd.conf.in"
    [ -s "$fd_file" ] || fd_file=/dev/null

    sed -e "s/@name@/$qname/" \
	-e "s/@director@/$qdirector/" \
	-e "s/@password@/$qpassword/" \
	"$fd_file"
}
