#HOSTS_CHARSET='utf-8'
HOSTS_INCLUDE="etc/hosts"

# absolute path!
ZONES_INCLUDE="$SRV/var/zones"

NAMED_CHECKZONE=/usr/sbin/named-checkzone
NAMED_SERVICE=bind9

## Generate forward zone from hosts hosts using pvl.hosts-forward
#
#   update_hosts_forward $out $src
function update_hosts_forward {
    local out="$1"
    local src="$2"
    local msg="$out: Generating forward hosts zone: $src"
    local include_cache=$(include_cache_path $src)
    local srcs=($(include_cache $include_cache))

    if apply_check "$out" ${srcs[@]:-}; then
        log_skip "$msg"
    else
        log_apply "$msg"
    
        apply_cmd "$out" $OPT/bin/pvl.hosts-forward \
            --hosts-include=$HOSTS_INCLUDE \
            --hosts-include-trace=$include_cache \
             "$src"
    fi
}

## Generate reverse zone from hosts hosts using pvl.hosts-reverse
#
#   update_hosts_reverse $out $src
function update_hosts_reverse {
    local out="$1"
    local src="$2"
    local msg="$out: Generating reverse hosts zone: $src"
    local include_cache=$(include_cache_path $src)
    local srcs=($(include_cache $include_cache))

    if apply_check "$out" ${srcs[@]:-}; then
        log_skip "$msg"
    else
        log_apply "$msg"
    
        apply_cmd "$out" $OPT/bin/pvl.hosts-reverse \
            --hosts-include="$HOSTS_INCLUDE" \
            --hosts-include-trace=$include_cache \
             "$src"
    fi
}

function update_zone_include {
    local out="$1"
    local src="$2"
    local msg="$out: Copy zone include: $src"

    if apply_check "$out" "${@:2}"; then
        log_skip "$msg"
    else
        log_apply "$msg"

        apply_cmd "$out" cat \
            "$src"
    fi
}


## Update list of zone $INCLUDEs from zone file
#
#   update_zone_includes var/include-cache/$zone etc/zones/$zone
#
function update_zone_includes {
    local out="$1"
    local src="$2"
    local includes="$ZONES_INCLUDE"

    if [ "$UPDATE_INCLUDES" = 1 ]; then
        log_force "$out: Force zone includes: $src"
    
    elif apply_check "$out" "$src"; then
        log_skip "$out: Skip zone includes: $src"
        
        return

    elif [ "$UPDATE_INCLUDES" = 0 ]; then
        log_noop "$out: Noop zone includes: $src"
        
        return
    else
        log_apply "$out: Update zone includes: $src"
    fi

    apply_cmd "$out" $OPT/bin/pvl.dns-includes \
            --include-path=$ZONES_INCLUDE \
            "$src"
}

## Update the cached .serial for the given zone, if the zone has changed:
#
#   update_serial var/serials/$zone $serial $deps...
#
# Supports UPDATE_SERIAL=
function update_zone_serial {
    local out="$1"
    local serial="$2"

    local old=$(test -e "$out" && cat "$out" || echo '')
    
    # test
    if [ "$UPDATE_SERIAL" = 1 ]; then
        log_force "$out: Force serial $old <- $serial"

    elif apply_check "$out" "${@:3}"; then
        log_skip "$out: Skip serial: $old <- $serial"
        
        return

    elif [ "$UPDATE_SERIAL" = 0 ]; then
        log_noop "$out: Noop serial: $old <- $serial"
        
        return

    else
        log_apply "$out: Update serial: $old <- $serial"
    fi

    echo "$serial" > $out
}

## Generate zone file from source using pvl.dns-process:
#
#   update_zone var/zones/$zone etc/zones/$zone var/serials/$zone
#
# Sets the SOA serial, and adjusts the $INCLUDE paths
function update_zone {
    local out="$1"
    local src="$2"
    local serial="$3"
    local serial_opt=
    local msg="$out: Generate zone: $src"

    if [ -n "$serial" -a -f "$serial" ]; then
        serial_opt="--serial=$(cat "$serial")"
    elif [ "$UPDATE_SERIAL" = 0 ]; then
        warn "$out: omit noop'd serial"
    else
        fail "$out: missing serial: $serial"
    fi

    if apply_check "$out" "${@:2}"; then
        log_skip "$msg"
    else
        log_apply "$msg"

        apply_cmd "$out" $OPT/bin/pvl.dns-process \
                $serial_opt \
                --include-path=$ZONES_INCLUDE \
                "$src"
    fi
}

## Test zone file for validity using named-checkzone:
#
#   check_zone      ..../$zone $origin
function test_zone {
    local zone=$1
    local origin=$2

    log_check "$zone: Checking zone @$origin..." 

    # checkzone is very specific about the order of arguments, -q must be first
    test_cmd $zone \
        $NAMED_CHECKZONE $origin $zone
}

## Load update zonefiles into bind:
#
#   reload_zones    
function reload_zones {
    if [ "$UPDATE_RELOAD" = 1 ]; then
        log_force "Reload zones"
        
    elif [ "$UPDATE_RELOAD" = 0 ]; then
        log_noop "Skip reload zones"
        
        return
    
    elif ! service_status $NAMED_SERVICE; then
        log_skip "named not running; did not restart"

        return
 
    else
        log_apply "Reload zones"
    fi

    service_reload $NAMED_SERVICE
}
