--[[ $%BEGINLICENSE%$
 Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.

 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; version 2 of the
 License.

 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 the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 02110-1301  USA

 $%ENDLICENSE%$ --]]

local tokenizer    = require("proxy.tokenizer")
local parser       = require("proxy.parser")
local commands     = require("proxy.commands")
local auto_config  = require("proxy.auto-config")

-- init global counters

if not proxy.global.config.histogram then
	proxy.global.config.histogram = {
		collect_queries = true,
		collect_tables = true
	}
end

-- init query counters
if not proxy.global.norm_queries then
	proxy.global.norm_queries = { }
end

-- init table-usage
if not proxy.global.tables then
	proxy.global.tables = { }
end

function read_query(packet)
	local cmd = commands.parse(packet)

	local r = auto_config.handle(cmd)
	if r then return r end

	if cmd.type == proxy.COM_QUERY then
		local tokens     = assert(tokenizer.tokenize(cmd.query))
		local norm_query = tokenizer.normalize(tokens)

		-- print("normalized query: " .. norm_query)

		if norm_query == "SELECT * FROM `histogram` . `queries` " then
			proxy.response = {
				type = proxy.MYSQLD_PACKET_OK,
				resultset = {
					fields = { 
						{ type = proxy.MYSQL_TYPE_STRING,
						  name = "query" },
						{ type = proxy.MYSQL_TYPE_LONG,
						  name = "count" },
						{ type = proxy.MYSQL_TYPE_LONG,
						  name = "max_query_time" },
						{ type = proxy.MYSQL_TYPE_FLOAT,
						  name = "avg_query_time" },
					}
				}
			}

			local rows = {}
			if proxy.global.norm_queries then
				for k, v in pairs(proxy.global.norm_queries) do
					rows[#rows + 1] = { 
						k, 
						v.count,
						v.max_query_time,
						v.avg_query_time,
					}
				end
			end
			
			proxy.response.resultset.rows = rows

			return proxy.PROXY_SEND_RESULT
		elseif norm_query == "DELETE FROM `histogram` . `queries` " then
			proxy.response = {
				type = proxy.MYSQLD_PACKET_OK,
			}

			proxy.global.norm_queries = {}
			return proxy.PROXY_SEND_RESULT
		elseif norm_query == "SELECT * FROM `histogram` . `tables` " then
			proxy.response = {
				type = proxy.MYSQLD_PACKET_OK,
				resultset = {
					fields = { 
						{ type = proxy.MYSQL_TYPE_STRING,
						  name = "table" },
						{ type = proxy.MYSQL_TYPE_LONG,
						  name = "reads" },
						{ type = proxy.MYSQL_TYPE_LONG,
						  name = "writes" },
					  }
				}
			}

			local rows = {}
			if proxy.global.tables then
				for k, v in pairs(proxy.global.tables) do
					rows[#rows + 1] = { 
						k, 
						v.reads,
						v.writes,
					}
				end
			end
			
			proxy.response.resultset.rows = rows

			return proxy.PROXY_SEND_RESULT
		elseif norm_query == "DELETE FROM `histogram` . `tables` " then
			proxy.response = {
				type = proxy.MYSQLD_PACKET_OK,
			}

			proxy.global.tables = {}
			return proxy.PROXY_SEND_RESULT
		end

		if proxy.global.config.histogram.collect_queries or
		   proxy.global.config.histogram.collect_tables then
			proxy.queries:append(1, packet)

			return proxy.PROXY_SEND_QUERY
		end
	end
end

function read_query_result(inj) 
	local cmd = commands.parse(inj.query)

	if cmd.type == proxy.COM_QUERY then
		local tokens     = assert(tokenizer.tokenize(cmd.query))
		local norm_query = tokenizer.normalize(tokens)

		if proxy.global.config.histogram.collect_queries then
			if not proxy.global.norm_queries[norm_query] then
				proxy.global.norm_queries[norm_query] = {
					count = 0,
					max_query_time = 0,
					avg_query_time = 0
				}
			end
	
			-- set new max if necessary
			if inj.query_time > proxy.global.norm_queries[norm_query].max_query_time then
				proxy.global.norm_queries[norm_query].max_query_time = inj.query_time
			end
	
			-- build rolling average
			proxy.global.norm_queries[norm_query].avg_query_time = 
				((proxy.global.norm_queries[norm_query].avg_query_time * proxy.global.norm_queries[norm_query].count) +
					inj.query_time) / (proxy.global.norm_queries[norm_query].count + 1)
			
			proxy.global.norm_queries[norm_query].count = proxy.global.norm_queries[norm_query].count + 1
		end
	
		if proxy.global.config.histogram.collect_tables then
			-- extract the tables from the queries
			tables = parser.get_tables(tokens)
	
			for table, qtype in pairs(tables) do
				if not proxy.global.tables[table] then
					proxy.global.tables[table] = {
						reads = 0,
						writes = 0
					}
				end
	
				if qtype == "read" then
					proxy.global.tables[table].reads = proxy.global.tables[table].reads + 1
				else
					proxy.global.tables[table].writes = proxy.global.tables[table].writes + 1
				end
			end
		end
	end
end
