--[[
	meowbot
	Copyright (C) 2008-2009 Park Jeong Min <pjm0616_at_gmail_d0t_com>

	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 3 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, see <http://www.gnu.org/licenses/>.
]]--

items_per_page = 40


remember_dbfile = './data/cmd_remember.sdb'
remember_db = nil

function open_remember_db()
	remember_db = sqlite3.open(remember_dbfile)
	if not remember_db then
		print('ERROR: failed to open database')
	end
	create_remember_db_table()
end
function close_remember_db()
	remember_db = nil
end

function create_remember_db_table()
	remember_db:prepare([[
		CREATE TABLE IF NOT EXISTS remember_data 
		(
			id integer not null primary key AUTOINCREMENT, 
			nick text, 
			word text, 
			data text, 
			time integer default 0
		);
	]]):step()
end


function get_word(word)
	local row = remember_db:prepare_and_bind([[
		SELECT id, nick, word, data, time FROM remember_data
			WHERE word = ?
			LIMIT 1
		]], word):fetch_object()
	return row
end

function new_word(word, content, nick)
	local prev_entry = get_word(word)
	if prev_entry then
		return false
	end
	remember_db:prepare_and_bind([[
		INSERT INTO remember_data(nick, word, data, time)
			VALUES(?, ?, ?, ?)
		]], nick, word, content, os.time()):step()
	return 1
end

function update_word(id, content, nick)
	remember_db:prepare_and_bind([[
		UPDATE remember_data
			SET
				nick = ?,  data = ?,  time = ?
			WHERE
				id = ?
		]], nick, content, os.time(), id):step()
	
	return 2
end
function append_to_word(word, content, nick)
	local prev_entry = get_word(word)
	if not prev_entry then
		return false
	end
	content = prev_entry.data .. ' | ' .. content
	return update_word(prev_entry.id, content, nick)
end

function delete_word(word)
	local res = get_word(word)
	if not res then return false end
	local res = remember_db:prepare_and_bind('DELETE FROM remember_data WHERE id = ?', res.id):step()
	if res then
		return true
	end
	return false
end

function search_word(field, kwd, page)
	page = page - 1
	if page < 0 then page = 0 end
	
	local srchstart = items_per_page * page
	local srchend = items_per_page
	if field ~= 'nick' then kwd = '%' .. kwd .. '%' end
	local rows = remember_db:prepare_and_bind([[
			SELECT word FROM remember_data
				WHERE ]]..field..[[ LIKE ?
				LIMIT ?, ?
		]], kwd, srchstart, srchend):fetch_object_all()
	
	return rows
end

function get_wordcnt()
	return remember_db:prepare_and_bind('SELECT count(id) FROM remember_data'):fetch_array()[1]
end





--------------- 명령어 시작

function cmd_remember(isrv, who, msginfo, mdest, cmd, carg)
	local matches = pcre.match('(\\S+) (.*)', carg)
	if not matches then
		return isrv:privmsg(mdest, '사용법: !기억 <단어> <내용>')
	end
	local word, content = unpack(matches)
	word = strip_irc_colors(word)
	
	local res = new_word(word, content, who:getnick())
	if res then
		isrv:privmsgf_nh(mdest, '%s%J{을를} 기억했습니다.', word)
	else
		isrv:privmsgf_nh(mdest, 
			'%s%J{이가} 이미 존재합니다. !잊어 명령으로 지우거나 !덧붙 명령을 사용해주세요.', word)
	end
end

function cmd_append(isrv, who, msginfo, mdest, cmd, carg)
	local matches = pcre.match('(\\S+) (.*)', carg)
	if not matches then
		return isrv:privmsg(mdest, '사용법: !덧붙 <단어> <덧붙일 내용>')
	end
	local word, content = unpack(matches)
	word = strip_irc_colors(word)
	
	local res = append_to_word(word, content, who:getnick())
	if res then
		isrv:privmsgf_nh(mdest, '%s에 덧붙였습니다.', word)
	else
		isrv:privmsgf_nh(mdest, 
			'%s%J{이가} 존재하지 않습니다. 먼저 !기억 명령을 사용해 주세요.', word)
	end
end

function cmd_erase(isrv, who, msginfo, mdest, cmd, carg)
	local word = strip_irc_colors(carg):gsub(' ', '')
	if word == '' then
		return isrv:privmsg(mdest, '지울 단어를 입력하세요')
	end
	local res = delete_word(word)
	if res then
		isrv:privmsgf_nh(mdest, '%s을 삭제했습니다.', word)
	else
		isrv:privmsgf_nh(mdest, '%s%J{이가} 존재하지 않습니다.', word)
	end
end

function cmd_whatis(isrv, who, msginfo, mdest, cmd, carg)
	local word = strip_irc_colors(carg):gsub(' ', '')
	if word == '' then
		return isrv:privmsg(mdest, '단어를 입력하세요')
	end
	local res = get_word(word)
	if res then
		local timestr = os.date('%Y/%m/%d %H:%M:%S', res.time)
		isrv:privmsgf_nh(mdest, '%s: %s (by %s, at %s)', res.word, res.data, res.nick, timestr)
	else
		isrv:privmsgf_nh(mdest, '%s%J{이가} 존재하지 않습니다.', word)
	end
end


function print_search_result(isrv, mdest, res)
	if #res == 0 then
		isrv:privmsg(mdest, '검색 결과가 없습니다.')
	else
		local linebuffer = ''
		for i, v in pairs(res) do
			if linebuffer == '' then
				linebuffer = v.word
			else
				linebuffer = linebuffer .. ', ' .. v.word
			end
			if i % 20 == 0 then
				isrv:privmsg_nh(mdest, linebuffer)
				linebuffer = ''
			end
		end
		if linebuffer ~= '' then
			isrv:privmsg_nh(mdest, linebuffer)
			linebuffer = ''
		end
	end
end

function cmd_search(isrv, who, msginfo, mdest, cmd, carg)
	local matches = pcre.match('(\\S+) ?(\\d*)', carg)
	if not matches then
		return isrv:privmsg(mdest, '사용법: !찾아 <단어> {페이지}')
	end
	local word, page = unpack(matches)
	word = strip_irc_colors(word)
	if page == '' then page = 1 end
	
	local res = search_word('word', word, page)
	print_search_result(isrv, mdest, res)
end

function cmd_search_content(isrv, who, msginfo, mdest, cmd, carg)
	local matches = pcre.match('(\\S+) ?(\\d*)', carg)
	if not matches then
		return isrv:privmsg(mdest, '기억 본문을 검색합니다 | 사용법: !본문검색 <검색어> {페이지}')
	end
	local word, page = unpack(matches)
	word = strip_irc_colors(word)
	if page == '' then page = 1 end
	
	local res = search_word('data', word, page)
	print_search_result(isrv, mdest, res)
end

function cmd_search_nick(isrv, who, msginfo, mdest, cmd, carg)
	local matches = pcre.match('(\\S+) ?(\\d*)', carg)
	if not matches then
		return isrv:privmsg(mdest, '닉네임으로 기억을 검색합니다 | 사용법: !닉검색 <검색할 닉네임> {페이지}')
	end
	local word, page = unpack(matches)
	word = strip_irc_colors(word)
	if page == '' then page = 1 end
	
	local res = search_word('nick', word, page)
	print_search_result(isrv, mdest, res)
end

function cmd_wordcnt(isrv, who, msginfo, mdest, cmd, carg)
	isrv:privmsgf_nh(mdest, '%d개의 단어를 기억하고 있습니다.', get_wordcnt())
end

function cmd_nickwordcnt(isrv, who, msginfo, mdest, cmd, carg)
	local fnick = strip_irc_colors(carg):gsub(' ', '')
	if fnick == '' then
		return isrv:privmsg(mdest, '사용법: !닉기억개수 <닉네임>')
	end
	local cnt = remember_db:prepare_and_bind('SELECT count(id) FROM remember_data WHERE nick LIKE ?', fnick):fetch_array()[1]
	isrv:privmsgf_nh(mdest, '%s닉이 기억시킨 단어는 %d개입니다.', fnick, cnt)
end





function init(bot)
	open_remember_db()
	
	bot:register_cmd('기억해', cmd_remember)
	bot:register_cmd('기억', cmd_remember)
	bot:register_cmd('알려줘', cmd_whatis)
	bot:register_cmd('알려', cmd_whatis)
	bot:register_cmd('찾아줘', cmd_search)
	bot:register_cmd('찾아', cmd_search)
	bot:register_cmd('검색', cmd_search)
	bot:register_cmd('덧붙여', cmd_append)
	bot:register_cmd('덧붙', cmd_append)
	bot:register_cmd('잊어', cmd_erase)
	bot:register_cmd('지워', cmd_erase)
	bot:register_cmd('삭제', cmd_erase)
	bot:register_cmd('본문검색', cmd_search_content)
	bot:register_cmd('닉검색', cmd_search_nick)
	bot:register_cmd('기억개수', cmd_wordcnt)
	bot:register_cmd('닉기억개수', cmd_nickwordcnt)
end

function cleanup(bot)
	bot:unregister_cmd('기억해')
	bot:unregister_cmd('기억')
	bot:unregister_cmd('알려줘')
	bot:unregister_cmd('알려')
	bot:unregister_cmd('찾아줘')
	bot:unregister_cmd('찾아')
	bot:unregister_cmd('검색')
	bot:unregister_cmd('덧붙여')
	bot:unregister_cmd('덧붙')
	bot:unregister_cmd('잊어')
	bot:unregister_cmd('지워')
	bot:unregister_cmd('삭제')
	bot:unregister_cmd('본문검색')
	bot:unregister_cmd('닉검색')
	bot:unregister_cmd('기억개수')
	bot:unregister_cmd('닉기억개수')
	
	close_remember_db()
end





