#!/bin/sh
# SPDX-License-Identifier: Apache-2.0
# CDN Cache RPCD Backend for SecuBox
# Copyright (C) 2025 CyberMind.fr

. /lib/functions.sh
. /usr/share/libubox/jshn.sh

get_pkg_version() {
	local ctrl="/usr/lib/opkg/info/luci-app-cdn-cache.control"
	if [ -f "$ctrl" ]; then
		awk -F': ' '/^Version/ { print $2; exit }' "$ctrl"
	else
		echo "unknown"
	fi
}

PKG_VERSION="$(get_pkg_version)"

CACHE_DIR=$(uci -q get cdn-cache.main.cache_dir || echo "/var/cache/cdn-squid")
STATS_FILE="/var/run/cdn-cache-stats.json"
LOG_DIR="/var/log/cdn-cache"
LOG_FILE="$LOG_DIR/cache.log"
SQUID_CONF="/var/etc/cdn-cache-squid.conf"
CA_CERT="/etc/squid/ssl/ca.pem"

# Initialize stats file if not exists
init_stats() {
	if [ ! -f "$STATS_FILE" ]; then
		cat > "$STATS_FILE" << 'EOF'
{"hits":0,"misses":0,"bytes_saved":0,"bytes_served":0,"requests":0,"start_time":0}
EOF
	fi
}

# Get Squid cache manager info
get_squid_info() {
	local mgr_url="http://localhost:$(uci -q get cdn-cache.main.listen_port || echo 3128)/squid-internal-mgr"
	# Try to get info via squidclient if available
	if command -v squidclient >/dev/null 2>&1; then
		squidclient -h localhost mgr:info 2>/dev/null
	fi
}

# Get service status
get_status() {
	local enabled=$(uci -q get cdn-cache.main.enabled || echo "0")
	local running=0
	local pid=""
	local uptime=0
	local cache_size=0
	local cache_files=0
	local squid_installed=0
	local backend="squid"

	# Check if Squid is installed
	if command -v squid >/dev/null 2>&1; then
		squid_installed=1
	fi

	# Check if Squid is running (cdn-cache instance)
	if [ -f "/var/run/cdn-cache.pid" ]; then
		pid=$(cat /var/run/cdn-cache.pid 2>/dev/null)
		if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
			running=1
			local start_time=$(stat -c %Y "/var/run/cdn-cache.pid" 2>/dev/null || echo "0")
			local now=$(date +%s)
			uptime=$((now - start_time))
		fi
	fi

	# Fallback: check by process name
	if [ "$running" = "0" ]; then
		pid=$(pgrep -f "squid.*cdn-cache" | head -1)
		if [ -n "$pid" ]; then
			running=1
		fi
	fi

	# Get cache directory stats
	if [ -d "$CACHE_DIR" ]; then
		cache_size=$(du -sk "$CACHE_DIR" 2>/dev/null | cut -f1 || echo "0")
		cache_files=$(find "$CACHE_DIR" -type f 2>/dev/null | wc -l || echo "0")
	fi

	local listen_port=$(uci -q get cdn-cache.main.listen_port || echo "3128")
	local transparent=$(uci -q get cdn-cache.main.transparent || echo "1")
	local ssl_bump=$(uci -q get cdn-cache.main.ssl_bump || echo "0")
	local max_size=$(uci -q get cdn-cache.main.cache_size || echo "2048")

	# Get Squid version if installed
	local squid_version=""
	if [ "$squid_installed" = "1" ]; then
		squid_version=$(squid -v 2>/dev/null | head -1 | sed 's/.*Version //' | cut -d' ' -f1)
	fi

	# Check if CA cert exists
	local ca_cert_exists=0
	[ -f "$CA_CERT" ] && ca_cert_exists=1

	json_init
	json_add_string "version" "$PKG_VERSION"
	json_add_string "backend" "$backend"
	json_add_string "squid_version" "$squid_version"
	json_add_boolean "squid_installed" "$squid_installed"
	json_add_boolean "enabled" "$enabled"
	json_add_boolean "running" "$running"
	json_add_string "pid" "$pid"
	json_add_int "uptime" "$uptime"
	json_add_int "cache_size_kb" "$cache_size"
	json_add_int "cache_files" "$cache_files"
	json_add_int "max_size_mb" "$max_size"
	json_add_int "listen_port" "$listen_port"
	json_add_boolean "transparent" "$transparent"
	json_add_boolean "ssl_bump" "$ssl_bump"
	json_add_boolean "ca_cert_exists" "$ca_cert_exists"
	json_add_string "cache_dir" "$CACHE_DIR"
	json_dump
}

# Get cache statistics from Squid access log
get_stats() {
	init_stats

	local hits=0
	local misses=0
	local requests=0
	local bytes_served=0
	local bytes_saved=0

	# Parse Squid access log for stats
	local access_log="$LOG_DIR/access.log"
	if [ -f "$access_log" ]; then
		# Count cache HITs and MISSes from Squid log format
		# Format: timestamp elapsed client result/code size method url ...
		hits=$(grep -c "TCP_HIT\|TCP_MEM_HIT\|TCP_REFRESH_HIT\|TCP_IMS_HIT" "$access_log" 2>/dev/null || echo "0")
		misses=$(grep -c "TCP_MISS\|TCP_REFRESH_MISS\|TCP_CLIENT_REFRESH_MISS" "$access_log" 2>/dev/null || echo "0")
		requests=$(wc -l < "$access_log" 2>/dev/null || echo "0")

		# Sum bytes served (field 5 in squid log)
		bytes_served=$(awk '{sum += $5} END {print sum}' "$access_log" 2>/dev/null || echo "0")
		[ -z "$bytes_served" ] && bytes_served=0

		# Estimate bytes saved (cached hits * average object size)
		# This is an approximation - cached bytes don't get re-downloaded
		local avg_size=0
		if [ "$requests" -gt 0 ]; then
			avg_size=$((bytes_served / requests))
		fi
		bytes_saved=$((hits * avg_size))
	fi

	local total=$((hits + misses))
	local hit_ratio=0
	if [ "$total" -gt 0 ]; then
		hit_ratio=$((hits * 100 / total))
	fi

	# Convert to human readable
	local saved_mb=$((bytes_saved / 1048576))
	local served_mb=$((bytes_served / 1048576))

	json_init
	json_add_int "hits" "$hits"
	json_add_int "misses" "$misses"
	json_add_int "hit_ratio" "$hit_ratio"
	json_add_int "requests" "$requests"
	json_add_int "bytes_saved" "$bytes_saved"
	json_add_int "bytes_served" "$bytes_served"
	json_add_int "saved_mb" "$saved_mb"
	json_add_int "served_mb" "$served_mb"
	json_dump
}

# Get cache content list
get_cache_list() {
	json_init
	json_add_array "items"
	
	if [ -d "$CACHE_DIR" ]; then
		find "$CACHE_DIR" -type f -printf '%s %T@ %p\n' 2>/dev/null | \
		sort -k2 -rn | head -100 | while read size mtime path; do
			local filename=$(basename "$path")
			local domain=$(echo "$path" | sed -n 's|.*/\([^/]*\)/[^/]*$|\1|p')
			local age=$(( $(date +%s) - ${mtime%.*} ))
			
			json_add_object ""
			json_add_string "filename" "$filename"
			json_add_string "domain" "$domain"
			json_add_int "size" "$size"
			json_add_int "age" "$age"
			json_add_string "path" "$path"
			json_close_object
		done
	fi
	
	json_close_array
	json_dump
}

# Get top domains by cache usage (parsed from Squid access log)
get_top_domains() {
	json_init
	json_add_array "domains"

	local access_log="$LOG_DIR/access.log"
	if [ -f "$access_log" ]; then
		# Parse domains from URLs in access log
		# Extract domain from URL field (field 7) and count hits + bytes
		awk '
		{
			url = $7
			bytes = $5
			status = $4

			# Extract domain from URL
			gsub(/^https?:\/\//, "", url)
			gsub(/\/.*$/, "", url)
			gsub(/:[0-9]+$/, "", url)

			if (url != "" && url != "-") {
				domains[url]++
				domain_bytes[url] += bytes
				if (status ~ /HIT/) {
					domain_hits[url]++
				}
			}
		}
		END {
			for (d in domains) {
				print domains[d], domain_bytes[d], domain_hits[d], d
			}
		}
		' "$access_log" 2>/dev/null | sort -rn | head -20 | while read count bytes hits domain; do
			local size_kb=$((bytes / 1024))
			json_add_object ""
			json_add_string "domain" "$domain"
			json_add_int "requests" "$count"
			json_add_int "size_kb" "$size_kb"
			json_add_int "hits" "${hits:-0}"
			json_close_object
		done
	fi

	json_close_array
	json_dump
}

# Get bandwidth savings over time
get_bandwidth_savings() {
	local period="${1:-24h}"
	
	json_init
	json_add_string "period" "$period"
	json_add_array "data"
	
	# Generate sample data points (would be from real logs)
	local now=$(date +%s)
	local points=24
	local interval=3600
	
	case "$period" in
		"7d") points=168; interval=3600 ;;
		"30d") points=30; interval=86400 ;;
		*) points=24; interval=3600 ;;
	esac
	
	local i=0
	while [ "$i" -lt "$points" ]; do
		local ts=$((now - (points - i) * interval))
		# Simulated data - in production would read from logs
		local saved=$((RANDOM % 100 + 10))
		local total=$((saved + RANDOM % 50 + 20))
		
		json_add_object ""
		json_add_int "timestamp" "$ts"
		json_add_int "saved_mb" "$saved"
		json_add_int "total_mb" "$total"
		json_close_object
		
		i=$((i + 1))
	done
	
	json_close_array
	json_dump
}

# Get hit ratio over time
get_hit_ratio() {
	local period="${1:-24h}"
	
	json_init
	json_add_string "period" "$period"
	json_add_array "data"
	
	local now=$(date +%s)
	local points=24
	local interval=3600
	
	case "$period" in
		"7d") points=168; interval=3600 ;;
		"30d") points=30; interval=86400 ;;
		*) points=24; interval=3600 ;;
	esac
	
	local i=0
	while [ "$i" -lt "$points" ]; do
		local ts=$((now - (points - i) * interval))
		# Simulated data
		local ratio=$((RANDOM % 40 + 50))
		
		json_add_object ""
		json_add_int "timestamp" "$ts"
		json_add_int "ratio" "$ratio"
		json_close_object
		
		i=$((i + 1))
	done
	
	json_close_array
	json_dump
}

# Get cache size info
get_cache_size() {
	local total_kb=0
	local max_mb=$(uci -q get cdn-cache.main.cache_size || echo "1024")
	local max_kb=$((max_mb * 1024))
	
	if [ -d "$CACHE_DIR" ]; then
		total_kb=$(du -sk "$CACHE_DIR" 2>/dev/null | cut -f1 || echo "0")
	fi
	
	local usage_pct=0
	if [ "$max_kb" -gt 0 ]; then
		usage_pct=$((total_kb * 100 / max_kb))
	fi
	
	json_init
	json_add_int "used_kb" "$total_kb"
	json_add_int "max_kb" "$max_kb"
	json_add_int "usage_percent" "$usage_pct"
	json_add_int "free_kb" "$((max_kb - total_kb))"
	json_dump
}

# Get configured policies
get_policies() {
	json_init
	json_add_array "policies"
	
	config_load cdn-cache
	config_foreach _add_policy cache_policy
	
	json_close_array
	json_dump
}

_add_policy() {
	local section="$1"
	local enabled name domains extensions cache_time max_size priority
	
	config_get_bool enabled "$section" enabled 0
	config_get name "$section" name ""
	config_get domains "$section" domains ""
	config_get extensions "$section" extensions ""
	config_get cache_time "$section" cache_time 1440
	config_get max_size "$section" max_size 512
	config_get priority "$section" priority 1
	
	json_add_object ""
	json_add_string "id" "$section"
	json_add_boolean "enabled" "$enabled"
	json_add_string "name" "$name"
	json_add_string "domains" "$domains"
	json_add_string "extensions" "$extensions"
	json_add_int "cache_time" "$cache_time"
	json_add_int "max_size" "$max_size"
	json_add_int "priority" "$priority"
	json_close_object
}

# Get exclusions
get_exclusions() {
	json_init
	json_add_array "exclusions"
	
	config_load cdn-cache
	config_foreach _add_exclusion exclusion
	
	json_close_array
	json_dump
}

_add_exclusion() {
	local section="$1"
	local enabled name domains reason
	
	config_get_bool enabled "$section" enabled 0
	config_get name "$section" name ""
	config_get domains "$section" domains ""
	config_get reason "$section" reason ""
	
	json_add_object ""
	json_add_string "id" "$section"
	json_add_boolean "enabled" "$enabled"
	json_add_string "name" "$name"
	json_add_string "domains" "$domains"
	json_add_string "reason" "$reason"
	json_close_object
}

# Get recent logs
get_logs() {
	local count="${1:-50}"

	json_init
	json_add_array "logs"

	# Try access log first (more useful for CDN cache)
	local access_log="$LOG_DIR/access.log"
	local cache_log="$LOG_DIR/cache.log"

	if [ -f "$access_log" ]; then
		tail -n "$count" "$access_log" 2>/dev/null | while read line; do
			json_add_string "" "$line"
		done
	elif [ -f "$cache_log" ]; then
		tail -n "$count" "$cache_log" 2>/dev/null | while read line; do
			json_add_string "" "$line"
		done
	fi

	json_close_array
	json_dump
}

# Set enabled state
set_enabled() {
	local enabled="${1:-0}"
	
	uci set cdn-cache.main.enabled="$enabled"
	uci commit cdn-cache
	
	if [ "$enabled" = "1" ]; then
		/etc/init.d/cdn-cache start
	else
		/etc/init.d/cdn-cache stop
	fi
	
	json_init
	json_add_boolean "success" 1
	json_dump
}

# Purge entire cache
purge_cache() {
	# Stop Squid, clear cache, reinitialize
	/etc/init.d/cdn-cache stop 2>/dev/null

	if [ -d "$CACHE_DIR" ]; then
		rm -rf "$CACHE_DIR"/*
		mkdir -p "$CACHE_DIR"
		chown squid:squid "$CACHE_DIR" 2>/dev/null
	fi

	# Clear access log
	[ -f "$LOG_DIR/access.log" ] && : > "$LOG_DIR/access.log"

	# Reset stats
	cat > "$STATS_FILE" << 'EOF'
{"hits":0,"misses":0,"bytes_saved":0,"bytes_served":0,"requests":0,"start_time":0}
EOF

	# Reinitialize Squid cache and restart
	if [ -f "$SQUID_CONF" ]; then
		squid -f "$SQUID_CONF" -z 2>/dev/null
		sleep 2
	fi

	/etc/init.d/cdn-cache start 2>/dev/null

	logger -t cdn-cache "Cache purged by user"

	json_init
	json_add_boolean "success" 1
	json_add_string "message" "Cache purged successfully"
	json_dump
}

# Purge cache for specific domain
purge_domain() {
	local domain="$1"
	
	if [ -n "$domain" ] && [ -d "$CACHE_DIR/$domain" ]; then
		rm -rf "$CACHE_DIR/$domain"
		logger -t cdn-cache "Cache purged for domain: $domain"
		
		json_init
		json_add_boolean "success" 1
		json_add_string "message" "Cache purged for $domain"
		json_dump
	else
		json_init
		json_add_boolean "success" 0
		json_add_string "message" "Domain not found in cache"
		json_dump
	fi
}

# Purge expired entries
purge_expired() {
	local deleted=0
	local cache_valid=$(uci -q get cdn-cache.main.cache_valid || echo "1440")
	local max_age=$((cache_valid * 60))
	
	if [ -d "$CACHE_DIR" ]; then
		deleted=$(find "$CACHE_DIR" -type f -mmin +"$cache_valid" -delete -print 2>/dev/null | wc -l)
	fi
	
	logger -t cdn-cache "Purged $deleted expired entries"
	
	json_init
	json_add_boolean "success" 1
	json_add_int "deleted" "$deleted"
	json_dump
}

# Preload URL into cache
preload_url() {
	local url="$1"
	
	if [ -n "$url" ]; then
		local output=$(wget -q --spider "$url" 2>&1)
		local result=$?
		
		if [ "$result" -eq 0 ]; then
			logger -t cdn-cache "Preloaded: $url"
			json_init
			json_add_boolean "success" 1
			json_add_string "message" "URL preloaded"
			json_dump
		else
			json_init
			json_add_boolean "success" 0
			json_add_string "message" "Failed to preload URL"
			json_dump
		fi
	else
		json_init
		json_add_boolean "success" 0
		json_add_string "message" "No URL provided"
		json_dump
	fi
}

# Add new policy
add_policy() {
	local name="$1"
	local domains="$2"
	local extensions="$3"
	local cache_time="${4:-1440}"
	local max_size="${5:-512}"
	
	local section="policy_$(date +%s)"
	
	uci set cdn-cache.$section=cache_policy
	uci set cdn-cache.$section.enabled=1
	uci set cdn-cache.$section.name="$name"
	uci set cdn-cache.$section.domains="$domains"
	uci set cdn-cache.$section.extensions="$extensions"
	uci set cdn-cache.$section.cache_time="$cache_time"
	uci set cdn-cache.$section.max_size="$max_size"
	uci set cdn-cache.$section.priority=5
	uci commit cdn-cache
	
	json_init
	json_add_boolean "success" 1
	json_add_string "id" "$section"
	json_dump
}

# Remove policy
remove_policy() {
	local id="$1"
	
	if [ -n "$id" ]; then
		uci delete cdn-cache.$id
		uci commit cdn-cache
		
		json_init
		json_add_boolean "success" 1
		json_dump
	else
		json_init
		json_add_boolean "success" 0
		json_dump
	fi
}

# Add exclusion
add_exclusion() {
	local name="$1"
	local domains="$2"
	local reason="$3"
	
	local section="exclusion_$(date +%s)"
	
	uci set cdn-cache.$section=exclusion
	uci set cdn-cache.$section.enabled=1
	uci set cdn-cache.$section.name="$name"
	uci set cdn-cache.$section.domains="$domains"
	uci set cdn-cache.$section.reason="$reason"
	uci commit cdn-cache
	
	json_init
	json_add_boolean "success" 1
	json_add_string "id" "$section"
	json_dump
}

# Remove exclusion
remove_exclusion() {
	local id="$1"
	
	if [ -n "$id" ]; then
		uci delete cdn-cache.$id
		uci commit cdn-cache
		
		json_init
		json_add_boolean "success" 1
		json_dump
	else
		json_init
		json_add_boolean "success" 0
		json_dump
	fi
}

# Wrapper methods for specification compliance (rules = policies)
list_rules() {
	get_policies
}

add_rule() {
	add_policy "$@"
}

delete_rule() {
	remove_policy "$@"
}

# Set cache size limits
set_limits() {
	local max_size_mb="$1"
	local cache_valid="${2:-1440}"

	if [ -z "$max_size_mb" ]; then
		json_init
		json_add_boolean "success" 0
		json_add_string "error" "max_size_mb required"
		json_dump
		return
	fi

	uci set cdn-cache.main.cache_size="$max_size_mb"
	uci set cdn-cache.main.cache_valid="$cache_valid"
	uci commit cdn-cache

	logger -t cdn-cache "Cache limits updated: ${max_size_mb}MB, ${cache_valid}min validity"

	json_init
	json_add_boolean "success" 1
	json_add_string "message" "Cache limits updated"
	json_add_int "max_size_mb" "$max_size_mb"
	json_add_int "cache_valid_minutes" "$cache_valid"
	json_dump
}

# Clear statistics
clear_stats() {
	cat > "$STATS_FILE" << 'EOF'
{"hits":0,"misses":0,"bytes_saved":0,"bytes_served":0,"requests":0,"start_time":0}
EOF

	json_init
	json_add_boolean "success" 1
	json_dump
}

# Restart service
do_restart() {
	/etc/init.d/cdn-cache restart

	json_init
	json_add_boolean "success" 1
	json_dump
}

# Get CA certificate for download
get_ca_cert() {
	json_init

	if [ -f "$CA_CERT" ]; then
		local cert_content=$(cat "$CA_CERT" | base64 -w0)
		local cert_fingerprint=$(openssl x509 -in "$CA_CERT" -noout -fingerprint -sha256 2>/dev/null | sed 's/.*=//')
		local cert_subject=$(openssl x509 -in "$CA_CERT" -noout -subject 2>/dev/null | sed 's/subject=//')
		local cert_expires=$(openssl x509 -in "$CA_CERT" -noout -enddate 2>/dev/null | sed 's/notAfter=//')

		json_add_boolean "success" 1
		json_add_string "certificate" "$cert_content"
		json_add_string "fingerprint" "$cert_fingerprint"
		json_add_string "subject" "$cert_subject"
		json_add_string "expires" "$cert_expires"
	else
		json_add_boolean "success" 0
		json_add_string "error" "CA certificate not found"
	fi

	json_dump
}

# Enable/disable SSL bump
set_ssl_bump() {
	local enabled="${1:-0}"

	uci set cdn-cache.main.ssl_bump="$enabled"
	uci commit cdn-cache

	if [ "$enabled" = "1" ]; then
		logger -t cdn-cache "SSL bump enabled - restart required"
	else
		logger -t cdn-cache "SSL bump disabled - restart required"
	fi

	json_init
	json_add_boolean "success" 1
	json_add_boolean "restart_required" 1
	json_dump
}

# Main dispatcher
case "$1" in
	list)
		json_init
		json_add_object "status"
		json_close_object
		json_add_object "stats"
		json_close_object
		json_add_object "cache_list"
		json_close_object
		json_add_object "top_domains"
		json_close_object
		json_add_object "bandwidth_savings"
		json_add_string "period" "string"
		json_close_object
		json_add_object "hit_ratio"
		json_add_string "period" "string"
		json_close_object
		json_add_object "cache_size"
		json_close_object
		json_add_object "policies"
		json_close_object
		json_add_object "exclusions"
		json_close_object
		json_add_object "logs"
		json_add_int "count" 0
		json_close_object
		json_add_object "set_enabled"
		json_add_boolean "enabled" false
		json_close_object
		json_add_object "purge_cache"
		json_close_object
		json_add_object "purge_domain"
		json_add_string "domain" "string"
		json_close_object
		json_add_object "purge_expired"
		json_close_object
		json_add_object "preload_url"
		json_add_string "url" "string"
		json_close_object
		json_add_object "add_policy"
		json_add_string "name" "string"
		json_add_string "domains" "string"
		json_add_string "extensions" "string"
		json_add_int "cache_time" 0
		json_add_int "max_size" 0
		json_close_object
		json_add_object "remove_policy"
		json_add_string "id" "string"
		json_close_object
		json_add_object "add_exclusion"
		json_add_string "name" "string"
		json_add_string "domains" "string"
		json_add_string "reason" "string"
		json_close_object
		json_add_object "remove_exclusion"
		json_add_string "id" "string"
		json_close_object
		json_add_object "list_rules"
		json_close_object
		json_add_object "add_rule"
		json_add_string "name" "string"
		json_add_string "domains" "string"
		json_add_string "extensions" "string"
		json_add_int "cache_time" 0
		json_add_int "max_size" 0
		json_close_object
		json_add_object "delete_rule"
		json_add_string "id" "string"
		json_close_object
		json_add_object "set_limits"
		json_add_int "max_size_mb" 0
		json_add_int "cache_valid" 0
		json_close_object
		json_add_object "clear_stats"
		json_close_object
		json_add_object "restart"
		json_close_object
		json_add_object "get_ca_cert"
		json_close_object
		json_add_object "set_ssl_bump"
		json_add_boolean "enabled" false
		json_close_object
		json_dump
		;;
	call)
		case "$2" in
			status) get_status ;;
			stats) get_stats ;;
			cache_list) get_cache_list ;;
			top_domains) get_top_domains ;;
			bandwidth_savings)
				read -r input
				json_load "$input"
				json_get_var period period "24h"
				get_bandwidth_savings "$period"
				;;
			hit_ratio)
				read -r input
				json_load "$input"
				json_get_var period period "24h"
				get_hit_ratio "$period"
				;;
			cache_size) get_cache_size ;;
			policies) get_policies ;;
			exclusions) get_exclusions ;;
			logs)
				read -r input
				json_load "$input"
				json_get_var count count 50
				get_logs "$count"
				;;
			set_enabled)
				read -r input
				json_load "$input"
				json_get_var enabled enabled 0
				set_enabled "$enabled"
				;;
			purge_cache) purge_cache ;;
			purge_domain)
				read -r input
				json_load "$input"
				json_get_var domain domain ""
				purge_domain "$domain"
				;;
			purge_expired) purge_expired ;;
			preload_url)
				read -r input
				json_load "$input"
				json_get_var url url ""
				preload_url "$url"
				;;
			add_policy)
				read -r input
				json_load "$input"
				json_get_var name name ""
				json_get_var domains domains ""
				json_get_var extensions extensions ""
				json_get_var cache_time cache_time 1440
				json_get_var max_size max_size 512
				add_policy "$name" "$domains" "$extensions" "$cache_time" "$max_size"
				;;
			remove_policy)
				read -r input
				json_load "$input"
				json_get_var id id ""
				remove_policy "$id"
				;;
			add_exclusion)
				read -r input
				json_load "$input"
				json_get_var name name ""
				json_get_var domains domains ""
				json_get_var reason reason ""
				add_exclusion "$name" "$domains" "$reason"
				;;
			remove_exclusion)
				read -r input
				json_load "$input"
				json_get_var id id ""
				remove_exclusion "$id"
				;;
			list_rules) list_rules ;;
			add_rule)
				read -r input
				json_load "$input"
				json_get_var name name ""
				json_get_var domains domains ""
				json_get_var extensions extensions ""
				json_get_var cache_time cache_time 1440
				json_get_var max_size max_size 512
				add_rule "$name" "$domains" "$extensions" "$cache_time" "$max_size"
				;;
			delete_rule)
				read -r input
				json_load "$input"
				json_get_var id id ""
				delete_rule "$id"
				;;
			set_limits)
				read -r input
				json_load "$input"
				json_get_var max_size_mb max_size_mb 0
				json_get_var cache_valid cache_valid 1440
				set_limits "$max_size_mb" "$cache_valid"
				;;
			clear_stats) clear_stats ;;
			restart) do_restart ;;
			get_ca_cert) get_ca_cert ;;
			set_ssl_bump)
				read -r input
				json_load "$input"
				json_get_var enabled enabled 0
				set_ssl_bump "$enabled"
				;;
			*) echo '{"error":"Unknown method"}' ;;
		esac
		;;
	*)
		echo '{"error":"Unknown command"}'
		;;
esac
