local AceAddon = AceLibrary("AceAddon-2.0")
local L = AceLibrary("AceLocale-2.2"):new("Cartographer-Stats")
local Tourist = AceLibrary("Tourist-2.0")
local BZ = AceLibrary("Babble-Zone-2.2")
local bs = AceLibrary("Babble-Spell-2.2")
local Tablet = AceLibrary("Tablet-2.0")

L:RegisterTranslations("enUS", function() return {
	["Statistics"] = "Statistics",
	["Module Description"] = "Module to build statistical information about gathering professions.",
	["Reset Statistics Database"] = true,
	["Reload statistics database. WARNING: this will take some time"] = true,
	["Left side"] = true,
	["Right side"] = true,
	["Toggle side to display stats"] = true,
	["Toggle display frame"] = true,
	["Ctrl-Left-Click on map to open statistics window"] = true,
	["Gathering Statistics"] = true,
	["Stats to track"] = true,
	["Databases you with to track"] = true,
	["Best location"] = true,
	-- Most statistical info to add to tooltip
	-- and for things like auto-cleaning
	["Skill Required"] = true,
	["Last Seen"] = true,
	["Percentage of Total"] = true,
	["Count"] = true,
} end)  

L:RegisterTranslations("koKR", function() return {
	["Statistics"] = "통계",
	["Module Description"] = "전문 기술에 대한 통계 정보를 구축하는 모듈입니다.",
	["Reset Statistics Database"] = "통계 데이터베이스 초기화",
	["Reload statistics database. WARNING: this will take some time"] = "통계 데이터베이스를 다시 읽습니다. 경고: 이것은 몇 시간 걸립니다.",
	["Left side"] = "좌측 사이드",
	["Right side"] = "오른쪽 사이드",
	["Toggle side to display stats"] = "통계를 표시하기 위해 사이드를 토글합니다.",
	["Toggle display frame"] = "통계화면을 토글합니다.",
	["Ctrl-Left-Click on map to open statistics window"] = "통계 창을 열 지도위에 Ctrl+마우스 클릭하세요.",
	["Gathering Statistics"] = "통계 보기",
	["Stats to track"] = "전문기술 선택",
	["Databases you with to track"] = "통계를 보려는 전문 기술을 선택합니다.",
	["Best location"] = "가장 좋은 위치",
	-- Most statistical info to add to tooltip
	-- and for things like auto-cleaning
	["Skill Required"] = "숙련도 요구사항",
	["Last Seen"] = "가장 최근에 본 지역",
	["Percentage of Total"] = "백분율",
	["Count"] = "수량",
} end)  

L:RegisterTranslations("deDE", function() return {
	["Statistics"] = "Statistik",
	["Module Description"] = "Modul zum Aufbau statistischer Informationen zu Sammelberufen.",
	["Reset Statistics Database"] = "Statistik-Datenbank zur\195\188cksetzen",
	["Reload statistics database. WARNING: this will take some time"] = "Statistik-Datenbank neu laden. WARNUNG: Dies wird einige Zeit beanspruchen.",
	["Left side"] = "Links",
  ["Right side"] = "Rechts",
	["Toggle side to display stats"] = "Seite, auf der die Statistik angezeigt werden soll.",
	["Ctrl-Left-Click on map to open statistics window"] = "Strg-Linksklick auf die Karte \195\182ffnet das Statistikfenster.",
	["Gathering Statistics"] = "Sammelstatistik",
-- no idea yet what these two are for... -.-
  ["Stats to track"] = "Datenbankauswahl",
	["Databases you with to track"] = "F\195\188r die Statistik auszuwertende Datenbanken.",
	["Best location"] = "G\195\188nstigste Region",
  
  -- Most statistical info to add to tooltip
	-- and for things like auto-cleaning
	["Skill Required"] = "Erforderlicher Fertigkeitswert",
	["Last Seen"] = "Zuletzt gesehen",
	["Percentage of Total"] = "Anteil an der Gesamtmenge",
	["Count"] = "Anzahl",
} end)

L:RegisterTranslations("zhTW", function() return {
	["Statistics"] = "統計資料",
	["Module Description"] = "Cartographer 模組，提供採集統計資料。",
	["Reset Statistics Database"] = "重設統計資料庫",
	["Reload statistics database. WARNING: this will take some time"] = "重載統計資料庫。警告: 這將會需要一些時間",
	["Left side"] = "左邊",
	["Right side"] = "右邊",
	["Toggle side to display stats"] = "切換顯示統計資料位置",
	["Toggle display frame"] = "切換顯示框架",
	["Ctrl-Left-Click on map to open statistics window"] = "Ctrl-左擊: 打開統計資料視窗",
	["Gathering Statistics"] = "採集統計資料",
	["Stats to track"] = "追蹤資料",
	["Databases you with to track"] = "你想追蹤的資料庫",
	["Best location"] = "最佳位置",
	-- Most statistical info to add to tooltip
	-- and for things like auto-cleaning
	["Skill Required"] = "需要技能點數",
	["Last Seen"] = "最後看見",
	["Percentage of Total"] = "總數的百分比",
	["Count"] = "數量",
} end)  

L:RegisterTranslations("esES", function() return {
	["Statistics"] = "Estad\195\173sticas",
	["Module Description"] = "M\195\179dulo para crear informaci\195\179n estad\195\173stica sobre las profesiones de recolecci\195\179n.",
	["Reset Statistics Database"] = "Reestablecer la base de datos de estad\195\173sticas",
	["Reload statistics database. WARNING: this will take some time"] = "Recarga la base de datos de estad\195\173sticas. AVISO: esto puede llevar alg\195\186n tiempo",
	["Left side"] = "Lado izquierdo",
	["Right side"] = "Lado derecho",
	["Toggle side to display stats"] = "Determina el lado donde se muestran las estad\195\173sticas",
	["Ctrl-Left-Click on map to open statistics window"] = "Ctrl+Clic en el mapa para abrir la ventana de estad\195\173sticas",
	["Gathering Statistics"] = "Estad\195\173sticas de Recolecci\195\179n",
	["Stats to track"] = "Estad\195\173sticas a seguir",
	["Databases you with to track"] = "Base de datos sobre la que deseas realizar un seguimiento",
	["Best location"] = "Mejor lugar",
	-- Most statistical info to add to tooltip
	-- and for things like auto-cleaning
	["Skill Required"] = "Habilidad Requerida",
	["Last Seen"] = "Visto por \195\186ltima vez",
	["Percentage of Total"] = "Porcentaje del Total",
	["Count"] = "Cantidad",
} end)

local Cartographer_Stats = Cartographer:NewModule("Stats","AceEvent-2.0", "AceConsole-2.0","AceHook-2.1","AceDB-2.0")

-- this list DOESNT need localized
local skillLevels = {
	-- Ore
	["Copper"] 			  = 1,
	["Tin"]    			  = 65,
	["Incendicite"] 	  = 65,
	["Silver"] 			  = 75,
	["Lesser Bloodstone"] = 75,
	["Iron"]   			  = 125,
	["Indurium"] 		  = 150,
	["Gold"]   			  = 155,
	["Mithril"] 		  = 175,
	["Truesilver"] 		  = 230,
	["Dark Iron"] 		  = 230,	
	["Thorium"] 		  = 245,
	["Rich Thorium"]  	  = 275,
	["Fel Iron"] 		  = 300,
	["Adamantite"] 		  = 325,
	["Eternium"]		  = 325,
	["Rich Adamantite"]   = 350,
	["Khorium"] 		  = 375,
	-- Herbs
	["Silverleaf"] 			= 1,
	["Peacebloom"]			= 1,
	["Bloodthistle"] 		= 1,
	["Earthroot"] 			= 15,
	["Mageroyal"] 			= 50,
	["Swiftthistle"] 		= 50,
	["Briarthorn"] 			= 70,
	["Stranglekelp"] 		= 85,
	["Bruiseweed"] 			= 100,
	["Wild Steelbloom"] 	= 115,
	["Grave Moss"] 			= 120,
	["Kingsblood"] 			= 125,
	["Liferoot"] 			= 150,
	["Fadeleaf"] 			= 160,
	["Goldthorn"] 			= 170,
	["Khadgar's Whisker"] 	= 185,
	["Wintersbite"] 		= 195,
	["Firebloom"] 			= 205,
	["Purple Lotus"] 		= 210,
	["Wildvine"] 			= 210,
	["Arthas' Tears"] 		= 220,
	["Sungrass"] 			= 230,
	["Blindweed"] 			= 235,
	["Ghost Mushroom"] 		= 245,
	["Gromsblood"] 			= 250,
	["Golden Sansam"] 		= 260,
	["Dreamfoil"] 			= 270,
	["Mountain Silversage"] = 280,
	["Plaguebloom"] 		= 285,
	["Icecap"] 				= 290,
	["Black Lotus"] 		= 300,
	["Felweed"] 			= 300,
	["Fel Lotus"] 			= 300,
	["Dreaming Glory"] 		= 315,
	["Ragveil"] 			= 325,
	["Terocone"] 			= 325,
	["Flame Cap"] 			= 335,
	["Netherbloom"] 		= 350,
	["Nightmare Vine"] 		= 365,
	["Mana Thistle"] 		= 375,
	["Ancient Lichen"] 		= 375,
	-- Fish difficulty is by zone/ not sur ehow to mark this in stats
}

local statlist = {
	["Mining"] = bs["Mining"],
	["Herbalism"] = bs["Herbalism"],
	["Fishing"] = bs["Fishing"],
}
Cartographer_Stats:RegisterDB("Cartographer_StatsDB")
local tabletShown = false
function Cartographer_Stats:OnInitialize()
	self.title   = L["Statistics"]
	self.name    = L["Statistics"]
	self.author  = "Kagaro on Ysera"
	self.notes   = L["Module Description"]
	self.email   = "sal.scotto@gmail.com"
	self.version = "1.0"
	self.website = nil

	-- we enable server for stat tracking
	self:SetProfile("server")
	self:RegisterDefaults('server', {
	    ['*'] = false, -- special key
		["Mining"] = {
			["best"] = {},
			["stat"] = {},
			["seen"] = {},
			["tracking"] = true,
			["initialized"] = false,
			["calculated"] = false,
		},
		["Herbalism"] = {
			["best"] = {},
			["stat"] = {},
			["seen"] = {},
			["tracking"] = true,
			["initialized"] = false,
			["calculated"] = false,
		},
		["Fishing"] = {
			["best"] = {},
			["stat"] = {},
			["seen"] = {},
			["tracking"] = true,
			["initialized"] = false,
			["calculated"] = false,
		},
	})
	self:RegisterDefaults('profile',{
		['side'] = 'LEFT',
		['showmenu'] = {
			["Mining"] = true,
			["Herbalism"] = true,
			["Fishing"] = true,
		},
		['showsubmenu'] = {}
	})

	Cartographer.options.args.Stats = {
		name = L["Statistics"],
		desc = self.notes,
		handler = self,
		type = 'group',
		args = {
			resetdb = {
				name = L["Reset Statistics Database"],
				desc = L["Reload statistics database. WARNING: this will take some time"],
				type= 'execute',
				func = "ResetStats",
				confirm = L["Reload statistics database. WARNING: this will take some time"]
			},
			sidetoggle = {
				name = L["Left side"],
				desc = L["Toggle side to display stats"],
				type = 'toggle',
				get = function() return self.db.profile.side == "LEFT" end,
				set = function(v)
					local side = v and "LEFT" or "RIGHT"
					local opp = v and "RIGHT" or "LEFT"
					self.db.profile.side = side
					if tabletShown then
						Cartographer:ReleaseSideTablet(opp,self)
						Cartographer:AcquireSideTablet(side,self)
					end
				end,
				guiNameIsMap = true,
				map = {
					[true] = L["Left side"],
					[false] = L["Right side"],
				}
			},
			stat_group = {
				name = L["Stats to track"],
				desc = L["Databases you with to track"],
				type = 'group',
				args = {}
			},
			show_frame = {
				name = L["Toggle display frame"],
				desc = L["Toggle display frame"],
				type = 'execute',
				func = function() 
					if tabletShown then
						Cartographer:ReleaseSideTablet(self.db.profile.side, self)
						tabletShown = false
					else
						Cartographer:AcquireSideTablet(self.db.profile.side, self) -- also refreshes
						tabletShown = true
					end
				end
			},
			toggle = {
				name = AceLibrary("AceLocale-2.2"):new("Cartographer")["Enabled"],
				desc = AceLibrary("AceLocale-2.2"):new("Cartographer")["Suspend/resume this module."],
				type  = "toggle",
				order = -1,
				get   = function() return Cartographer:IsModuleActive(self) end,
				set   = function() Cartographer:ToggleModuleActive(self) end,				
			},
		},
		handler = self,
	}
	for k,v in pairs(statlist) do
		local v = v
		local k = k
		Cartographer.options.args.Stats.args.stat_group.args[k] = {
			name = v,
			desc = v,
			type = 'toggle',
			get = function() return self.db.server[k].tracking end,
			set = function() 
				self.db.server[k].tracking = not self.db.server[k].tracking 
				self.db.server[k].initialized = false
				self.db.server[k].calculated = false
				if tabletShown then
					self:InitStats()
					Cartographer:AcquireSideTablet(self.db.profile.side,self)
				end
			end,
			disabled = function() 
				if not Cartographer:HasModule(k) then
					self.db.server[k].tracking = false
					return true
				end
				return false
			end
		}
	end
end

function Cartographer_Stats:ResetStats()
	self:ResetDB("server")
	self:InitStats()
	if tabletShown then
		Cartographer:AcquireSideTablet(self.db.profile.side,self)
	end
end

-- this functions assumes your using the optimized db format found in mining/herbalism
-- fishing willl be tracked via process events
function Cartographer_Stats:processDB(database,statName)
	if database then
		for zone,data in pairs(database) do
			if type(data) == "table" then
				for id,note in pairs(data) do
					if type(note) == "string" then
						if not self.db.server[statName].stat[note] then
							self.db.server[statName].stat[note] = {}
						end
						self.db.server[statName].stat[note][zone] = (self.db.server[statName].stat[note][zone] or 0 ) + 1
					end
				end
			end
		end
		self.db.server[statName].initialized = true
	end
end

function Cartographer_Stats:InitStats()
-- lets go through all the databases
	if (not self.db.server["Mining"].initialized) and Cartographer:HasModule("Mining")  and self.db.server["Mining"].tracking then
		self:processDB(Cartographer_MiningDB,"Mining")
	end
	if (not self.db.server["Herbalism"].initialized) and Cartographer:HasModule("Herbalism") and self.db.server["Herbalism"].tracking then
		self:processDB(Cartographer_HerbalismDB,"Herbalism")
	end
	if (not self.db.server["Fishing"].initialized) and Cartographer:HasModule("Fishing") and self.db.server["Fishing"].tracking then
		self:processDB(Cartographer_FishingDB.fish,"Fishing")
	end
end

function Cartographer_Stats:OnEnable()
	-- register our listener
	self:StartEvents()
	self:InitStats()
	Cartographer:AddToMagnifyingGlass(L["Ctrl-Left-Click on map to open statistics window"])
	-- hook instance maps
	if Cartographer:GetInstanceWorldMapButton() then
		self:HookScript(Cartographer:GetInstanceWorldMapButton(), "OnClick", "SetupSideTablet")
	else
		self:RegisterEvent("Cartographer_RegisterInstanceWorldMapButton", function(frame)
			self:HookScript(frame, "OnClick", "SetupSideTablet")
		end)
	end
	-- hook the world map
	self:Hook("WorldMapButton_OnClick", true)
	if WorldMapFrame:IsShown() then
		Cartographer_Notes:RefreshMap(false)
	end

end

function Cartographer_Stats:OnDisable()
	self:StopEvents()
	-- Release any tablets
	Cartographer:ReleaseSideTablet("LEFT", self)
	Cartographer:ReleaseSideTablet("RIGHT", self)
	-- remove magnifying data
	Cartographer:RemoveFromMagnifyingGlass(L["Ctrl-Left-Click on map to open statistics window"])
	tabletShown = false
end

-- clean up any tablets when we close a map
function Cartographer_Stats:Cartographer_MapClosed()
	Cartographer:ReleaseSideTablet("LEFT", self)
	Cartographer:ReleaseSideTablet("RIGHT", self)
	tabletShown = false
end

function Cartographer_Stats:Cartographer_MapOpened()
	self:InitStats()
end

function Cartographer_Stats:StartEvents()
	self:RegisterEvent("CartographerNotes_NoteSet","NoteAdded")
	self:RegisterEvent("CartographerNotes_NoteDeleted","NoteRemoved")
	self:RegisterEvent("Cartographer_MapClosed")
	self:RegisterEvent("Cartographer_MapOpened")
	self:RegisterEvent("CartographerFishing_CaughtFish","NoteAdded")
end

function Cartographer_Stats:StopEvents()
	self:UnregisterAllEvents()
	self:UnhookAll()
end

-- note add callback
function Cartographer_Stats:NoteAdded(zone,x,y,icon,creator)
	--local stat = statlist[creator]
	if self.db.server[creator]  and self.db.server[creator].tracking then
		if not self.db.server[creator].stat[icon] then
			self.db.server[creator].stat[icon] = {}
		end
		self.db.server[creator].stat[icon][zone] = (self.db.server[creator].stat[icon][zone] or 0) + 1
		self.db.server[creator].calculated = false
	end
end
-- when a note is removed
function Cartographer_Stats:NoteRemoved(zone,x,y,icon,creator)
	--local stat = statlist[creator]
	if self.db.server[creator] and self.db.server[creator].tracking then
		if not self.db.server[creator].stat[icon] then
			self.db.server[creator].stat[icon] = {}
		end
		self.db.server[creator].stat[icon][zone] = (self.db.server[creator].stat[icon][zone] or 0) -1
		if self.db.server[creator].stat[icon][zone] < 0 then
			self.db.server[creator].stat[icon][zone] = 0
		end
		self.db.server[creator].calculated = false
	end
end
-- left click map
function Cartographer_Stats:WorldMapButton_OnClick(mouseButton,button)
	if mouseButton ~= "LeftButton" or not IsControlKeyDown() then
		return self.hooks.WorldMapButton_OnClick(mouseButton, button)
	end
	if tabletShown then
		Cartographer:ReleaseSideTablet(self.db.profile.side, self)
		tabletShown = false
	else
		Cartographer:AcquireSideTablet(self.db.profile.side, self) -- also refreshes
		tabletShown = true
	end
end
-- tablet functions here
function Cartographer_Stats:SetupSideTablet(frame, mouseButton)
	if mouseButton ~= "LeftButton" or not IsControlKeyDown() then
		return self.hooks[frame].OnClick(frame, mouseButton)
	end
	if tabletShown then
		Cartographer:ReleaseSideTablet(self.db.profile.side, self)
		tabletShown = false
	else
		Cartographer:AcquireSideTablet(self.db.profile.side, self) -- also refreshes
		tabletShown = true
	end
end
-- figure out best ore/herb
function Cartographer_Stats:CalcBest()
	for k,v in pairs(statlist) do
		if not self.db.server[k].calculated and self.db.server[k].tracking then
			for icon,zdata in pairs(self.db.server[k].stat) do
				local bZone = ""
				local bCount = 0
				local sZone = ""
				local sCount = 0
				local tZone = ""
				local tCount = 0
				local totalCount = 0
				for zone,count in pairs(zdata) do
					if count > bCount then
						tCount = sCount
						tZone = sZone
						sCount = bCount
						sZone = bZone
						bCount = count
						bZone = zone
					end
					totalCount = totalCount + count
				end
				self.db.server[k].best[icon] = {}
				self.db.server[k].best[icon].first = {}
				self.db.server[k].best[icon].first.zone = bZone
				self.db.server[k].best[icon].first.count = bCount
				self.db.server[k].best[icon].first.percent = string.format("%.2f%%",(bCount/totalCount)* 100)
				self.db.server[k].best[icon].second = {}
				self.db.server[k].best[icon].second.zone = sZone
				self.db.server[k].best[icon].second.count = sCount
				self.db.server[k].best[icon].second.percent = string.format("%.2f%%",(sCount/totalCount)* 100)
				self.db.server[k].best[icon].third = {}
				self.db.server[k].best[icon].third.zone = tZone
				self.db.server[k].best[icon].third.count = tCount
				self.db.server[k].best[icon].third.percent = string.format("%.2f%%",(tCount/totalCount)* 100)
				--self.db.server[k].best[icon] = bZone
			end
			self.db.server[k].calculated = true
		end
	end
end

-- when we draw the tablet
function Cartographer_Stats:OnTabletRequest()
	self:CalcBest()
	Tablet:SetTitle(L["Gathering Statistics"])
	self:DrawTablet()
end

function Cartographer_Stats:GetGatheringLocalization(key)
	if key == "Mining" then
		return AceLibrary("Babble-Ore-2.2")
	elseif key == "Herbalism" then
		return AceLibrary("Babble-Herbs-2.2")
	else
		return AceLibrary("Babble-Fish-2.2")
	end
end

function Cartographer_Stats:DrawTablet()
	for k,v in pairs(statlist) do
		if self.db.server[k].tracking and Cartographer:HasModule(k) then
			local ll = self:GetGatheringLocalization(k)
			local cat = Tablet:AddCategory(
				'columns',5,
				'text',v,
				'text2',L["Best location"],
				'font',GameTooltipHeaderText,
				'justify2','LEFT',
				'func', function()
					self.db.profile.showmenu[k] = not self.db.profile.showmenu[k]
					Cartographer:AcquireSideTablet(self.db.profile.side,self)
				end,
				'showWithoutChildren',true,
				'checked',true,
				'hasCheck',true,
				'checkIcon', self.db.profile.showmenu[k] and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up")
			if self.db.profile.showmenu[k] then
				for note,zonedata in pairs(self.db.server[k].best) do
					local scat = cat:AddLine(
						'columns',5,
						'text',ll[note],
						'text2',L["Count"],
						'text3',L["Percentage of Total"],
						'justify2','LEFT',
						'func', function()
							self.db.profile.showsubmenu[note] = not self.db.profile.showsubmenu[note]
							Cartographer:AcquireSideTablet(self.db.profile.side,self)
						end,
						'checked',true,
						'textR',1,'textG',1,'textB',1,
						'text2R',1,'text2G',1,'text2B',1,
						'text3R',1,'text3G',1,'text3B',1,
						'showWithoutChildren',true,
						'hasCheck',true,
						'checkIcon', self.db.profile.showsubmenu[note] and "Interface\\Buttons\\UI-MinusButton-Up" or "Interface\\Buttons\\UI-PlusButton-Up")
					if self.db.profile.showsubmenu[note] then
						if BZ:HasTranslation(zonedata.first.zone) then
							cat:AddLine('text',BZ[zonedata.first.zone],'text2',zonedata.first.count,'text3',zonedata.first.percent,'justify','LEFT','justify2','LEFT','justify3','LEFT','noInherit',true)
						end
						if BZ:HasTranslation(zonedata.second.zone) then
							cat:AddLine('text',BZ[zonedata.second.zone],'text2',zonedata.second.count,'text3',zonedata.second.percent,'justify','LEFT','justify2','LEFT','justify3','LEFT','noInherit',true)
						end
						if BZ:HasTranslation(zonedata.third.zone) then
							cat:AddLine('text',BZ[zonedata.third.zone],'text2',zonedata.third.count,'text3',zonedata.third.percent,'justify','LEFT','justify2','LEFT','justify3','LEFT','noInherit',true)
						end
					end
					--scat:AddLine('text',ll[note],'text2',BZ[zone],'textR', 1,'textG', 1,'textB', 1,'text2R', 0.5,'text2G', 1,'text2B', 0, 'justify2','LEFT','justify','LEFT','noInherit', true)
				end
			end
		end
	end
end

Cartographer_Stats.OnCartographerLeftTabletRequest = Cartographer_Stats.OnTabletRequest
Cartographer_Stats.OnCartographerRightTabletRequest = Cartographer_Stats.OnTabletRequest
                                         