//      infobot.gib
//
//      Infobot for QuakeForge 0.5.3
//
//      Copyright (C) 2003  Brian Koropoff
//
//      This program is free software; you can redistribute it and/or
//      modify it under the terms of the GNU General Public License
//      as published by the Free Software Foundation; either version 2
//      of the License, or (at your option) any later version.
//
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//      See the GNU General Public License for more details.
//
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to:
//
//              Free Software Foundation, Inc.
//              59 Temple Place - Suite 330
//              Boston, MA  02111-1307, USA
//

domain infobot

global rcsid = "$Id$"

global facts addr_cmds cmds 

function infobot::makeKey {
	return $(regex::replace $args[1] "\." -- "\_")_
}

function infobot::hasAccess {
	return $(equal $(client::getInfo $args[1] "infopass") $infobot_password)
}

function infobot::defineFactoid {
	if (!$infobot_restrict_factoids || $(infobot::hasAccess $args[1])) {
		key = $(infobot::makeKey $args[2])
		// Don't modify locked factoids
		if ${facts.${key}[2]} {
			return -2
		}
		// Filter out newlines/carriage returns
		facts.${key}[0] = $(regex::replace $args[3] "[\n\r]" g "")
		// Dump the rest at the end of the array (any meta info can be stored here)
		facts.${key}[1] = @args[4:]
		return 0
	}
	return -1
}

function infobot::factToString {
	for i in @args[1:] {
		out = $out, $i, "\255"
	}
	return $out
}

function infobot::saveFactoids {
	// Build up output to write to a file
	for fact in %facts {
		output = $output, $fact, "\255", $(infobot::factToString @facts.$fact), "\n"
	}
	file::write $args[1],".fct" $output
}

function infobot::loadFactoids {
	for line in $(split $(file::read $args[1],".fct") "\n") {
		fact = $(split $line "\255")
		facts.${fact[0]} = @fact[1:]
	}
	current_file = $args[1]
}

function infobot::say {
	client::printAllChat $infobot_name, ": ", $args[1], "\n"
}

function infobot::tell {
	client::printChat $args[1] "[priv] ",$infobot_name, ": ", $args[1], "\n"
}

function infobot::chatEvent {
	// Ignore teamtalk/spectalk
	if $args[3] {
		return
	}
	
	uid = $args[1]
	from = $(client::getInfo $uid "name")
	mesg = $args[2]
	
	// see if we are being addressed by name
	res = $(regex::extract $mesg $infobot_name, "[:,][[:space:]]+(.+)" i)
	if #res {
		mesg = $res[2]
		local addr = 1
	} else {
		local addr = 0
	}
	
	res = $(regex::extract $mesg "([^[:space:]]+)[\?!]$" --)
	if #res {
		local key = $(infobot::makeKey $res[2])
		if #{facts.$key} {
			if $addr {
				infobot::say $from, ": ", $res[2], " ", ${facts.${key}[1]}, " ", ${facts.$key}, "."
			} else {
				infobot::say "Well, ", $res[2], " ", ${facts.${key}[1]}, " ", ${facts.$key}, "."
			}
		} else if $addr { // Nothing found, and we were addressed
			infobot::say $from, ": Sorry, I don't know anything about ", $res[2], "."
		}
		return
	}
	res = $(regex::extract $mesg "^([^[:space:]]+)[[:space:]]+(is|are)[[:space:]]+(.+)" i)
	if #res {
		res = $(infobot::defineFactoid $args[1] $res[2] $res[4] $res[3])
		if $addr {
			if ($res == -1) {
				infobot::say $from, ": You do not have the privileges to alter factoids."
			} else if ($res == -2) {
				infobot::say $from, ": That factoid is locked."
			} else {
				infobot::say $from, ": Understood."
			}
		}
		return
	}
	
	cmd = $(split $mesg)
	if $addr {
		if #{addr_cmds.$cmd} {
			${addr_cmds.$cmd} $args[1] $from @cmd[1:];
		} else {
			infobot::say $from, ": I'm sorry, I don't understand."
		}
	} else if #{cmds.$cmd} {
		${cmds.$cmd} $args[1] $from @cmd[1:];
	}
}

function infobot::cmdAddrRegister {
	addr_cmds.$args[1] = $args[2]
}

function infobot::cmdRegister {
	cmds.$args[1] = $args[2]
}

function infobot::forgetFactoid_f {
	if ($infobot_restrict_factoids && !$(infobot::hasAccess $args[1])) {
		say $args[2], ": You do not have the privileges to alter factoids."
		return
	}
	fact = $(infobot::makeKey $args[3])
	if #{facts.$fact} {
		if ${facts.${fact}[2]} {
			infobot::say $args[2], ": That factoid is locked."
		} else {
			delete facts.$fact
			infobot::say $args[2], ": I forgot about ", $args[3], "."
		}
	} else {
		infobot::say $args[2], ": I don't know anything about ", $args[3], "."
	}
}

function infobot::lockFactoid_f {
	ifnot $(infobot::hasAccess $args[1]) {
		infobot::say $args[2], ": You do not have the privileges to lock factoids."
		return
	}
	fact = $(infobot::makeKey $args[3])
	ifnot #{facts.$fact} {
		infobot::say $args[2], ": No such factoid exists."
		return
	}
	facts.${fact}[2] = 1
	infobot::say $args[2], ": \"", $args[3], "\" is now locked."
}

function infobot::unlockFactoid_f {
	ifnot $(infobot::hasAccess $args[1]) {
		infobot::say $args[2], ": You do not have the privileges to unlock factoids."
		return
	}
	fact = $(infobot::makeKey $args[3])
	ifnot #{facts.$fact} {
		infobot::say $args[2], ": No such factoid exists."
		return
	}
	facts.${fact}[2] = 0
	infobot::say $args[2], ": \"", $args[3], "\" is now unlocked."
}

function infobot::stats_f {
	infobot::say $args[2], ": I currently reference ", $(count %facts), " factoid(s) and ", ($(count %cmds) + $(count %addr_cmds)), " command(s)."
}

function infobot::syncFactoids_f {
	ifnot $(infobot::hasAccess $args[1]) {
		infobot::say $args[2], ": You do not have syncing privileges."
		return
	}
	if #args[3] {
		file = $args[3]
	} else {
		file = "default"
	}
	infobot::saveFactoids $file
	infobot::say $args[2], ": Factoids successfully synced to file ", $file, ".fct."
}

function infobot::loadFactoids_f {
	ifnot $(infobot::hasAccess $args[1]) {
		infobot::say $args[2], ": You do not have loading privileges."
		return
	}
	if #args[3] {
		file = $args[3]
	} else {
		file = "default"
	}
	ifnot $(count $(file::find $file,".fct")) {
		infobot::say $args[2], ": That factoids file does not exist."
		return
	}
	infobot::loadFactoids $file
	infobot::say $args[2], ": Factoids successfully loaded from file ", $file, ".fct."
}
	
function infobot::forgetAllFactoids_f {
	ifnot $(infobot::hasAccess $args[1]) {
		infobot::say $args[2], ": You do not have amnesia privileges."
		return
	}
	infobot::say $args[2], ": I have forgotten all factoids."
	delete facts
	global facts
}

// These are useful to the admin
function::export infobot::saveFactoids infobot::loadFactoids

event::register chat infobot::chatEvent
infobot::cmdAddrRegister	"forget"	infobot::forgetFactoid_f
infobot::cmdAddrRegister	"lock"		infobot::lockFactoid_f
infobot::cmdAddrRegister	"unlock"	infobot::unlockFactoid_f
infobot::cmdAddrRegister	"infostats"	infobot::stats_f
infobot::cmdAddrRegister	"sync"		infobot::syncFactoids_f
infobot::cmdAddrRegister	"load"		infobot::loadFactoids_f
infobot::cmdAddrRegister	"amnesia"	infobot::forgetAllFactoids_f

// Set default values
ifnot $(length $infobot_restrict_factoids) {
	set infobot_restrict_factoids 0
}

ifnot $(length $infobot_password) {
	set infobot_password "hackme"
}

ifnot $(length $infobot_name) {
	set infobot_name "gib"
}

// Try to load a default factoids file
if $(count $(file::find default.fct)) {
	infobot::loadFactoids "default"
}
