-- The MIT License (MIT) http://opensource.org/licenses/MIT
-- Copyright (c) 2014-2016 His Dad

-- Some code from the luatz project (MIT Licence)

-- Configuration ==========
--local dateformat = "%Y-%m-%d, %H:%M"
local dateformat_log = "%Y-%m-%d, %H:%M:%S"
local FG_Colour_Not_Complete = "#FFB67D"
local FG_Colour_Complete = "#000000"
local BG_Colour_Not_Complete = "#FFB67D"
local BG_Colour_Complete = "#A4FF5A"
local Colour_Heading_Complete = "#58FA58"
--force_lang = "fr"   --	or "de" or "en"  for debugging

-- ========================
version= "38"
require( "iuplua" )
require( "iupluacontrols" )
iup.SetGlobal("UTF8MODE","YES")
dofile "../../SavedVariables/History.lua"
Craglorn_Dat={}
Craglorn_Order={"N","V","VH"}
Grp_Dat={}

Grp_Order={"1N","1V","1VH","2N","2V","2VH"}
Grp1_Order={"1N","1V","1VH"}
Grp2_Order={"2N","2V","2VH"}

for _,i in ipairs(Grp_Order) do
	Grp_Dat[i]={}
end
for _,i in ipairs(Craglorn_Order) do
	Craglorn_Dat[i]={}
end

dofile "./data/Keys.lua"		--Linking tables, must do first
dofile "./data/DLC.lua"			--Achievement to Grid lookup, language independent
dofile "./data/Group1.lua"		-- Grp Mode 1 data, N, V, VH
dofile "./data/Group2.lua"		-- Grp Mode 2 data, N, V, VH
dofile "./data/Public.lua"
dofile "./data/Quest.lua"
dofile "./data/Veteran.lua"		-- Auxillary Achievements for Vet Dungeons
dofile "./data/WB.lua"
dofile "./data/Craglorn.lua"
dofile "./data/Special.lua"		-- Record of non standard Achievment ID's we need to keep.
dofile "./data/utility.lua"		-- utility functions

-- generate_id ()			-- Generate the file the addon uses to filter Achievement ID's
-- Uncomment when need to run.


-- generate achievement lookups from key (cell)
for _,i in ipairs(Grp_Order) do
	Grp_Dat[i].reverse_id = reverse_id(Grp_Dat[i].id)
end

for _,i in ipairs(Craglorn_Order) do
	Craglorn_Dat[i].reverse_id = reverse_id(Craglorn_Dat[i].id)
end

Pub_Dat.reverse_id = reverse_id(Pub_Dat.id)
DLC_Dat.reverse_id = reverse_id(DLC_Dat.id)

lingua= {}		-- Translated data
load_lang = function (lang)
	if lingua[lang] ~= nil
	then return
	end

	local path = "./data/" .. lang .. "/"

	dofile (path .. lang .. ".lua")
	dofile (path .. lang .."-data.lua")			--Achievement Data from game
	lingua[lang] = {}

	lingua[lang].Area_names = Area_names		-- dofile writes to global variables
	lingua[lang].L = L
	lingua[lang].pub_names = pub_names
	lingua[lang].grp_names = grp_names
	lingua[lang].DLC_Location_names = DLC_Location_names
	lingua[lang].DLC_names = DLC_names
	lingua[lang].Ach_Detail = Ach_Detail
end




--SQ_Dat loaded  from data.lua
SQ_Info= {} -- keyed by "LC" string as the  ZONE Identifier
for id,_ in pairs (SQ_dat) do  -- Load all Quest Data by Achievement ID
		local L = SQ_dat[id].L
		local C = SQ_dat[id].C
		local key = tostring(L) .. tostring(C)	-- make name key

		if SQ_Info[key] == nil then
			SQ_Info[key] = {}
			SQ_Info[key].quests = {}
		end
		table.insert(SQ_Info[key].quests,id)
end


accounts = {}
accounts_list = {}		-- String list for selection dialog
playerNames = {}		-- Get name from ID.

for acc,_ in pairs(History_SV["Default"]) do
	accounts[acc] = {}
	accounts[acc].worlds = {}
	accounts[acc].hasblankworlds = false
	accounts[acc].player = {}
	accounts[acc].playerIDs = {}	-- intermediate table for sorting. WIP. Controls presentation order
	accounts[acc].playerIDs_vet= {}	-- subset of names which are >L50
	table.insert(accounts_list, acc)

  -- ===	Load Language Tables
    accounts[acc].lang = (History_SV["Default"][acc]["$AccountWide"].lang)
	if accounts[acc].lang == nil then
		accounts[acc].lang = "en"
	end

	if force_lang ~= nil then
		accounts[acc].lang = force_lang	-- Force the language for testing
	end
	load_lang(accounts[acc].lang)
	-- Reset Globals
	Area_names = lingua[accounts[acc].lang].Area_names
	L = lingua[accounts[acc].lang].L
	pub_names = lingua[accounts[acc].lang].pub_names
	grp_names = lingua[accounts[acc].lang].grp_names
	DLC_names = lingua[accounts[acc].lang].DLC_names
	DLC_Location_names = lingua[accounts[acc].lang].DLC_Location_names
	Ach_Detail = lingua[accounts[acc].lang].Ach_Detail
-- load worlds
	nworlds = 0
	if History_SV["Default"][acc]["$AccountWide"]["worlds"] ~= nil then
		for i,j in pairs(History_SV["Default"][acc]["$AccountWide"]["worlds"]) do
			nworlds = nworlds +1
			table.insert(accounts[acc].worlds, i)
		end
	end

-- insert marker for older chars
--	table.insert(accounts[acc].worlds, "##NEITHER##")


-- Load Character Data
	for playerID, _ in pairs(History_SV["Default"][acc]["$AccountWide"]["data"]) do

		if playerID == "" then
		print("acct: " .. acc)
		end
		table.insert (accounts[acc].playerIDs, playerID)
		accounts[acc].player[playerID] = {}		-- stub table to hold char data, later becomes "me"
--
		local me = accounts[acc].player[playerID]											-- shorter reference: our code
		local thischar = History_SV["Default"][acc]["$AccountWide"]["data"][playerID]	-- shorter reference: History DB
		-- Pull in some char data for processing
		if thischar.name == nil  then --	Old Format
	--	    print("Old Format  " .. playerID)
			me.name = playerID
		else
			me.name = thischar.name
		end
		playerNames[playerID]=me.name

		-- == Gender
		if thischar.Gender =="M" then
			me.gender = L.Male
		elseif thischar.Gender == "F" then
			me.gender = L.Female
		end
		-- ==Level
		local level = thischar.level

		me.level = level
		if (level <=50) then
			me.levelstr = tostring(level)
			me.isvet = false
		else
			me.levelstr = "V" .. tostring(level -50)
			me.isvet = true
			table.insert(accounts[acc].playerIDs_vet,playerID)
		end
		-- == Cumulative TimePlayed
		if thischar.timeplayed == nil then
			me.timeplayed = math.floor(thischar.levels[level].time/60)   -- Old version compat
		else
			me.timeplayed = math.floor(thischar.timeplayed/60)
		end
		-- world

		if thischar.world == nil then
			accounts[acc].hasblankworlds = true		-- causes display of "##NEITHER##
		else
			me.world = thischar.world		-- server
		end

	end

	table.sort(accounts[acc].playerIDs,function(a,b)  return (playerNames[a] < playerNames[b]) end)
	table.sort(accounts[acc].playerIDs_vet,function(a,b) return (playerNames[a] < playerNames[b]) end)
end



--[[ ==========================================
	Iterate over all accounts and PlayerIDs creating display items
--]]
 for acc,_ in pairs (accounts) do

  -- ====  Accountwide Data
  -- Setup Log data
	accounts[acc].logtabs  =iup.tabs{}
	-- Log Display table presentation
	accounts[acc].logtable = {}
	accounts[acc].logtable=iup.matrix{numcol=2, numcol_visible=2,  numlin=0,numlin_visible=8}
	accounts[acc].logtable:setcell(0,0, L.TStamp)
	iup.SetAttribute(accounts[acc].logtable,  "ALIGNMENT0", "ACENTER")
	iup.SetAttribute(accounts[acc].logtable,  "ALIGNMENT2", "ALEFT")
	iup.SetAttribute(accounts[acc].logtable,  "WIDTH0", 80)
	iup.SetAttribute(accounts[acc].logtable,  "WIDTH1", 100)
	iup.SetAttribute(accounts[acc].logtable,  "WIDTH2", 300)
	iup.SetAttribute(accounts[acc].logtable,  "READONLY", "YES")
	-- Load log data

	local Line=0
	local TimeStr = ""
	accounts[acc].logtable.numlin = Line
	for _,j in ipairs (History_SV["Default"][acc]["$AccountWide"]["log"]) do
		Line= Line +1
		accounts[acc].logtable.numlin = Line
		TimeStr = os.date(dateformat_log,j["TimeStamp"])
		accounts[acc].logtable:setcell( Line,0, TimeStr)
		if j["Char"] ~= nil then
			accounts[acc].logtable:setcell( Line,1, j["Char"])
		end
		accounts[acc].logtable:setcell( Line,2, j["text"])
	end

	-- Setup Log Display
	accounts[acc].log_tab=iup.vbox {
			["tabtitle"] =L.LogTab,
			accounts[acc].logtable,
			iup.fill{}
			}
	-- Top Level Panels
	-- accounts[acc].world_zbox = iup.zbox{}  -- display main panel containing worlds (servers)  -- not used ATM
	accounts[acc].mode_zbox = iup.zbox{}  -- display submain panel containing tabs and dungeons
	accounts[acc].char_tabs = iup.tabs{}  -- Top level of Char_Tabs, Character Info in Here
	accounts[acc].dung_tabs = iup.tabs{}  -- Top level of Dung_Tabs, Dungeon  Info in Here


	iup.Append(accounts[acc].mode_zbox, accounts[acc].char_tabs)

	detail_name = iup.label {title="",expand = "HORIZONTAL"}
	detail_desc = iup.label {title="",expand = "HORIZONTAL"}
	Status_bar = iup.label{title=L.Welcome .. " " .. L.Version .. " " .. version .. ".", expand = "HORIZONTAL"}
	iup.Append(accounts[acc].mode_zbox, accounts[acc].dung_tabs)

  -- Mode Buttons (Toggles)
  --[[  These control the display.
   Char mode lists the characters and information for them (default for prior versions)
   Dung Mode lists the dungeons and which characters have done them.
   Buttons are arranged in radio mode
   --]]

   accounts[acc].char_tog = iup.toggle{ title = L.Characters}
  local tog = accounts[acc].char_tog
  function tog:action(x)
	if x == 1 then
	accounts[acc].mode_zbox.value =accounts[acc].char_tabs
	end
  end

  accounts[acc].dung_tog = iup.toggle{ title = L.Dungeons}

  tog = accounts[acc].dung_tog
  function tog:action(x)
	if x == 1 then
	accounts[acc].mode_zbox.value = accounts[acc].dung_tabs
	end
  end
  accounts[acc].mode = iup.frame {
								iup.radio {
								iup.hbox{
										accounts[acc].char_tog,
										accounts[acc].dung_tog,
										},
									}
								}
  accounts[acc].mode.title =  L.Mode
  accounts[acc].mode.margin = "15x5"

  -- Prepare for Dungeon data recording as we iterate through characters.
  accounts[acc].dung = {}		-- put all dungeon mode stuff here. Populate it with character data.
  -- N Normal,   V Vet,    VH   Vet hard mode
  dung = accounts[acc].dung
  dung.pub = {}
  dung.pub.box = {}
  dung.pub.key = {}
  dung.DLC = {}
  dung.DLC.box = {}
  dung.DLC.key = {}

  dung.Grp = {}		-- these ones are indexed.
  dung.Craglorn = {}

  -- Set up dungeon mode Group Dungeons
  for _,i in ipairs(Grp_Order) do
	dung.Grp[i]= {}
	dung.Grp[i].key ={}   -- key lookup
	dung.Grp[i].box = iup.matrix {numcol=#accounts[acc].playerIDs,  numlin=_size(Grp_Dat[i].id), widthdef=100}
	iup.SetAttribute(dung.Grp[i].box, "READONLY", "YES")

	dung.Grp[i].tab = iup.vbox {
						["tabtitle"] =L.Grp_TabName[i],
						dung.Grp[i].box,
						iup.fill{},
					}

-- Mouseover
	dung.Grp[i].box.dat = Grp_Dat[i]
	dung.Grp[i].box.mousemove_cb = box_mousemove_cb
	dung.Grp[i].box.leavewindow_cb = box_leavewindow_cb

		--set lines Heading
	dung.Grp[i].box:setcell(0,0, L.Location)
	--Set Line titles
	for line,key in ipairs(Grp_Dat[i].key) do
		dung.Grp[i].box:setcell(line, 0, grp_names[key])
	end

	--Create Columns for Chars
	for col ,playerID in ipairs(accounts[acc].playerIDs) do
		dung.Grp[i].box:setcell(0, col, playerNames[playerID])
	end


  end

  -- a table for each dungeon to which we add characters
  for _,i in ipairs(Grp1_Order) do
    for _,key in ipairs(grp1tokey) do
	  dung.Grp[i].key[key] = {}
	  for _,playerID in ipairs(accounts[acc].playerIDs) do
		dung.Grp[i].key[key][playerID] = false
	  end
	end
  end

  for _,i in ipairs(Grp2_Order) do
    for _,key in ipairs(grp2tokey) do
	  dung.Grp[i].key[key] = {}
	  for _,playerID in ipairs(accounts[acc].playerIDs) do
		dung.Grp[i].key[key][playerID] = false
	  end
	end
  end

  -- Set up dungeon mode Craglorn Trials
  for _,i in ipairs(Craglorn_Order) do
		dung.Craglorn[i]= {}
		dung.Craglorn[i].key ={}   -- key lookup
		dung.Craglorn[i].box = iup.matrix {numcol=#accounts[acc].playerIDs,  numlin=_size(Craglorn_Dat[i].id), widthdef=100}
		iup.SetAttribute(dung.Craglorn[i].box, "READONLY", "YES")

		dung.Craglorn[i].tab = iup.vbox {
							["tabtitle"] =L.Crag_TabName[i],
							dung.Craglorn[i].box,
							iup.fill{},
						}

	dung.Craglorn[i].box.dat = Craglorn_Dat[i]
	dung.Craglorn[i].box.mousemove_cb = box_mousemove_cb
	dung.Craglorn[i].box.leavewindow_cb = box_leavewindow_cb

	--set lines Heading
	dung.Craglorn[i].box:setcell(0,0, L.Location)
	--Set Line titles
	for line,key in ipairs(Craglorn_Dat[i].key) do
		dung.Craglorn[i].box:setcell(line, 0, Craglorn_Names[i][key])
	end

	--Create Columns for Chars
	for col ,playerID in ipairs(accounts[acc].playerIDs) do
		dung.Craglorn[i].box:setcell(0, col, playerNames[playerID])
	end



    -- a table for each dungeon to which we add characters
	for _,key in ipairs(Craglorn2key[i]) do
	  dung.Craglorn[i].key[key] = {}
	  for _,playerID in ipairs(accounts[acc].playerIDs) do
		dung.Craglorn[i].key[key][playerID] = false
	  end
	end

  end




  for _,i in ipairs(Pub_Dat.key) do
	  dung.pub.key[i] = {}
  end

  for _,i in ipairs(DLC2key) do
	  dung.DLC.key[i] = {}
  end

  -- ================  END Accountwide Data

  --=================  START OF CHARACTER MODE DISPLAY

-- Creates boxes, stage from names to allow sorting
	for _,playerID in ipairs(accounts[acc].playerIDs) do
		local me = accounts[acc].player[playerID]											-- shorter reference: our code
		local thischar = History_SV["Default"][acc]["$AccountWide"]["data"][playerID]	-- shorter reference: History DB


		-- Generate the leveling box.  ============================

		me.leveling_box = iup.matrix {numcol=6, numcol_visible=6,  widthdef=60}
		me.leveling_box:setcell(0,1, L.Level)
		me.leveling_box:setcell(0,2, L.PTime)
		me.leveling_box:setcell(0,3, L.Start)
		me.leveling_box:setcell(0,4, L.Deaths)
		me.leveling_box:setcell(0,5, L.APts)
		me.leveling_box:setcell(0,6, L.Location)
		iup.SetAttribute(me.leveling_box, "WIDTH6", "100")
		iup.SetAttribute(me.leveling_box, "READONLY", "YES")


		-- levels as stored are unsorted, so create a level table which is sorted,
		local levels = {}
		for i,_ in pairs(thischar.levels) do
			table.insert(levels, i)
		end

		table.sort(levels)

		for i,j in ipairs(levels) do		-- traverse in sorted order
			local timelevel = math.floor(thischar.levels[j].time)
			me.leveling_box.numlin = i
			me.leveling_box:setcell(i,1, j)
			me.leveling_box:setcell(i,2, math.floor(timelevel/60))
			me.leveling_box:setcell(i,3, os.date("%Y-%m-%d",thischar.levels[j].begin))
			me.leveling_box:setcell(i,4, thischar.levels[j].deaths)
			me.leveling_box:setcell(i,5, thischar.levels[j].Ach_Points)
			-- Do we have map name for this level?
			if thischar.levels[j].map ~= nil then
				me.leveling_box:setcell(i,6, thischar.levels[j].map)
			end
		end
		-- Create Grp Dungeon Boxes ====================================
		me.Grp ={}		-- Put them all together

		for _, i in ipairs(Grp_Order) do		-- For Each Grp Dungeon
			me.Grp[i] = {}						--  Dungeon data storage
			me.Grp[i].vet = Grp_Dat[i].vet
			me.Grp[i].box = iup.matrix {numcol=4, numcol_visible=4,  numlin=Grp_Dat[i].lines, widthdef=100}
			iup.SetAttribute(me.Grp[i].box, "READONLY", "YES")

			me.Grp[i].box.dat = Grp_Dat[i]		-- for mouseover
			me.Grp[i].box.mousemove_cb = box_mousemove_cb
			me.Grp[i].box.leavewindow_cb = box_leavewindow_cb

			--Set Column titles in box
			for j=1, 4 do
				me.Grp[i].box:setcell(0,j, Area_names[j].long)
			end


			-- set background to red
		--	iup.SetAttribute(me.Grp[i].box,  "BGCOLOR", BG_Colour_Not_Complete)

			-- set text to black if achievement found.

			for id, Gdat in pairs (Grp_Dat[i].id) do
				local bgcolour,key
				if thischar.ach[id] ~= nil then
					bgcolour = "BGCOLOR" .. Gdat.L .. ":" .. Gdat.C
					iup.SetAttribute(me.Grp[i].box, bgcolour, BG_Colour_Complete)
					-- Add char to dungeon
					key = tostring(Gdat.L .. Gdat.C)
					dung.Grp[i].key[key][playerID] = true
				else
					bgcolour = "BGCOLOR" .. Gdat.L .. ":" .. Gdat.C
					iup.SetAttribute(me.Grp[i].box, bgcolour, BG_Colour_Not_Complete)
				end
			end

			-- Create display tab
			me.Grp[i].tab = iup.vbox {
						["tabtitle"] =L.Grp_TabName[i],
						me.Grp[i].box,
						iup.fill{},
				}
		end

		-- these IDs are in Specials.lua
		--Set background of heading if all done
		if thischar.ach[1073] ~= nil then  --EP Vanquisher
				iup.SetAttribute(me.Grp["1N"].box,  "BGCOLOR0:1", Colour_Heading_Complete)
		end

		if thischar.ach[1074] ~= nil then  --DC Vanquisher
				iup.SetAttribute(me.Grp["1N"].box ,  "BGCOLOR0:2", Colour_Heading_Complete)
		end

		if thischar.ach[1075] ~= nil then  --AD Vanquisher
				iup.SetAttribute(me.Grp["1N"].box ,  "BGCOLOR0:3", Colour_Heading_Complete)
		end

		for _,i in ipairs(Grp_Order) do
			for _, id in pairs (Grp_Dat[i].id) do
				local key = tostring(id.L).. tostring(id.C)	-- make name key
				me.Grp[i].box:setcell(id.L, id.C, grp_names[key])
			end
		end

		-- Create Craglorn Dungeon Boxes ====================================
		me.Craglorn ={}		-- Put them all together

		for _, i in ipairs(Craglorn_Order) do		-- For Each Dungeon
			me.Craglorn[i] = {}						-- Dungeon data storage
			me.Craglorn[i].vet = Craglorn_Dat[i].vet
			me.Craglorn[i].box = iup.matrix {numcol=1, numcol_visible=1, numlin=_size(Craglorn_Dat[i].id), widthdef=100}
			iup.SetAttribute(me.Craglorn[i].box, "READONLY", "YES")
			me.Craglorn[i].box.dat = Craglorn_Dat[i]		-- for mouseover
			me.Craglorn[i].box.mousemove_cb = box_mousemove_cb
			me.Craglorn[i].box.leavewindow_cb = box_leavewindow_cb

			--Set Column titles in box
			for line,key in ipairs (Craglorn2key[i]) do  -- Load Dungeons Name. Info LC is the Dungeon Identifier
					me.Craglorn[i].box:setcell(line,0, Craglorn_Names[i][key])
			end


			iup.SetAttribute(me.Craglorn[i].box,  "BGCOLOR*:1", BG_Colour_Not_Complete)
			--iup.SetAttribute(me.Craglorn[i].box,  "FGCOLOR*:1", "DEFAULT")
			-- set text if achievement found and change background
			for id, Gdat in pairs (Craglorn_Dat[i].id) do
				local bgcolour
				if thischar.ach[id] ~= nil then
					bgcolour = "BGCOLOR" .. Gdat.L .. ":" .. Gdat.C
					me.Craglorn[i].box:setcell(Gdat.L,Gdat.C, L.YesLabel)
					iup.SetAttribute(me.Craglorn[i].box, bgcolour, BG_Colour_Complete)
					-- Add char to dungeon
					dung.Craglorn[i].key[Gdat.key][playerID] = true
				else
					me.Craglorn[i].box:setcell(Gdat.L,Gdat.C, L.NoLabel)
				end

			end

			-- Create display tab
			me.Craglorn[i].tab = iup.vbox {
						["tabtitle"] =L.Crag_TabName[i],
						me.Craglorn[i].box,
						iup.fill{},
				}
		end


		-- Create Pub Dungeon Achievements Box==========================
		me.Pub_box = iup.matrix {numcol=4, numcol_visible=4,  numlin=5, widthdef=100}
		iup.SetAttribute(me.Pub_box, "READONLY", "YES")
		me.Pub_box.dat = Pub_Dat
		me.Pub_box.mousemove_cb = box_mousemove_cb
		me.Pub_box.leavewindow_cb = box_leavewindow_cb

		for i=1, 4 do  -- Load text
			me.Pub_box:setcell(0,i, Area_names[i].long)
		end

		iup.SetAttribute(me.Pub_box,  "BGCOLOR" , BG_Colour_Not_Complete)

		for id,_ in pairs (Pub_Dat.id) do
			local bgcolour = "BGCOLOR" .. Pub_Dat.id[id].L .. ":" .. Pub_Dat.id[id].C
			if thischar.ach[id] ~= nil then
				iup.SetAttribute(me.Pub_box, bgcolour, BG_Colour_Complete)
				-- Add char to dungeon
				local key = tostring(Pub_Dat.id[id].L .. Pub_Dat.id[id].C)
				dung.pub.key[key][playerID] = true
			else
				iup.SetAttribute(me.Pub_box, bgcolour, BG_Colour_Not_Complete)
			end
		end

		if thischar.ach[1068] ~= nil then  --EP Conqueror
				iup.SetAttribute(me.Pub_box,  "BGCOLOR0:1", Colour_Heading_Complete)
		end

		if thischar.ach[1070] ~= nil then  --DC Conqueror
				iup.SetAttribute(me.Pub_box,  "BGCOLOR0:2", Colour_Heading_Complete)
		end

		if thischar.ach[1069] ~= nil then  --AD Conqueror
				iup.SetAttribute(me.Pub_box,  "BGCOLOR0:3", Colour_Heading_Complete)
		end

		for id,dat in pairs (Pub_Dat.id) do  -- Load text
				local key = tostring(tostring(dat.L) .. tostring(dat.C))	-- make name key
				local dname = pub_names[key]
					if dname == nil then
				dname = "key " .. key .." not found in pub_names"
				end
				me.Pub_box:setcell(dat.L,dat.C,dname)
		end

		-- Create Locations Box==============================================
		me.Map_box= iup.matrix {numcol=6, numcol_visible=6,  numlin=0, widthdef=70}

		me.Map_box:setcell(0,0, L.Location)
		me.Map_box:setcell(0,1, L.Visits)
		me.Map_box:setcell(0,2, L.FirstVisited)
		me.Map_box:setcell(0,3, L.FirstLevel)
		me.Map_box:setcell(0,4, L.TimesLeveled)
		me.Map_box:setcell(0,5, L.FirstDeath)
		me.Map_box:setcell(0,6, L.Deaths)

		iup.SetAttribute(me.Map_box, "READONLY", "YES")
		iup.SetAttribute(me.Map_box, "ALIGNMENT0", "ALEFT")
		iup.SetAttribute(me.Map_box, "WIDTH0", "100")
		iup.SetAttribute(me.Map_box, "WIDTH1", "40")
		iup.SetAttribute(me.Map_box, "WIDTH4", "55")
		iup.SetAttribute(me.Map_box, "WIDTH6", "40")


		local map_names = {}
		for map,_ in pairs(thischar.maps) do
			table.insert(map_names,map)
		end

		table.sort(map_names)
		local Line =1
		for _, map in ipairs(map_names) do
			me.Map_box.numlin = Line

			me.Map_box:setcell( Line,0, map)

			if thischar.maps[map].visit ~= nil then
				me.Map_box:setcell( Line,1, thischar.maps[map].visit)
			end

			if thischar.maps[map].firstvisitdate ~= nil then
				local firstvisit = os.date(dateformat,thischar.maps[map].firstvisitdate)
				me.Map_box:setcell( Line,2, firstvisit)
			end

			if thischar.maps[map].firstlevel ~= nil then
				me.Map_box:setcell( Line,3, thischar.maps[map].firstlevel)
			end

			if thischar.maps[map].timeslevel ~= nil then
				me.Map_box:setcell( Line,4, thischar.maps[map].timeslevel)
			end

			if thischar.maps[map].firstdeathlevel ~= nil then
				me.Map_box:setcell( Line,5, thischar.maps[map].firstdeathlevel)
			end

			if thischar.maps[map].deaths ~= nil then
				me.Map_box:setcell( Line,6, thischar.maps[map].deaths )
			end
		Line= Line +1
		end
-- Create WorldBoss Achievements Box==========================
		me.WB_box= iup.matrix {numcol=4, numcol_visible=4,  numlin=5, widthdef=110}

		for i=1, 4 do  -- Load headings, not craglorn
			me.WB_box:setcell(0,i, Area_names[i].long)
		end
		me.WB_box:setcell(0,0, L.Zone)
		me.WB_box:setcell(1,0, "1")
		me.WB_box:setcell(2,0, "2")
		me.WB_box:setcell(3,0, "3")
		me.WB_box:setcell(4,0, "4")
		me.WB_box:setcell(5,0, "5")
		iup.SetAttribute(me.WB_box, "READONLY", "YES")
		iup.SetAttribute(me.WB_box, "ALIGNMENT0", "ACENTER")


		-- Need to keep track of multiple achievements for WB in Zones. Index them by zone LineColumn.
		WB_Info={}
		WB_Area={}
    local dname, key
		for id,_ in pairs (WB_dat) do  -- Load World Boss Name. Info LC is the ZONE Identifier
				local L = WB_dat[id].L
				local C = WB_dat[id].C
				local key = tostring(L) .. tostring(C)	-- make name key
				dname = Locations[key]				-- Zone Locations
				if dname == nil then
					dname = "key " .. key .." not found"
				end
				WB_Info[key] = {count = 0}
				WB_Area[C] =0
				me.WB_box:setcell(L,C,dname .. " (0)")
		end

		for id,_ in pairs (WB_dat) do  -- For Achievements we have..
			if thischar.ach[id] ~= nil then
				local L = WB_dat[id].L
				local C = WB_dat[id].C
				--Set colour of LC
				local bgcolour = "BGCOLOR" .. L .. ":" .. C

				key = tostring(L) .. tostring(C)	-- make name key
				dname = Locations[key]				-- Zone Locations
				if dname == nil then
					dname = "WB key " .. key .." not found"
				end
				-- Increment count and display
				WB_Info[key].count = WB_Info[key].count+1
				me.WB_box:setcell(L,C,dname .. " (" .. WB_Info[key].count ..")")
				--Check if done
				if  WB_Info[key].count >= 6 then
					iup.SetAttribute(me.WB_box, bgcolour , BG_Colour_Complete)
				end
				--Add to Area Completion
				WB_Area[C] = WB_Area[C] +1
			end
		end
		--Set Column Colours if 30 done.
		for i,j in pairs (WB_Area) do
			if j > 29 then
				iup.SetAttribute(me.WB_box,  "BGCOLOR0:".. tostring(i), Colour_Heading_Complete)
			end
		end

-- Create SkillQuest Achievements Box==========================

		me.SQ_box= iup.matrix {numcol=4, numcol_visible=4,  numlin=5, widthdef=110}
		me.SQ_Info = {}
		for i=1, 4 do  -- Load headings
			me.SQ_box:setcell(0,i, Area_names[i].long)
		end
		me.SQ_box:setcell(0,0, L.Zone)
		me.SQ_box:setcell(1,0, "1")
		me.SQ_box:setcell(2,0, "2")
		me.SQ_box:setcell(3,0, "3")
		me.SQ_box:setcell(4,0, "4")
		me.SQ_box:setcell(5,0, "5")
		iup.SetAttribute(me.SQ_box, "READONLY", "YES")
		iup.SetAttribute(me.SQ_box, "ALIGNMENT0", "ACENTER")

		iup.SetAttribute(me.SQ_box,  "FGCOLOR*:1", FG_Colour_Not_Complete)
		iup.SetAttribute(me.SQ_box,  "FGCOLOR*:2", FG_Colour_Not_Complete)
		iup.SetAttribute(me.SQ_box,  "FGCOLOR*:3", FG_Colour_Not_Complete)
		iup.SetAttribute(me.SQ_box,  "FGCOLOR*:4", FG_Colour_Not_Complete)
		iup.SetAttribute(me.SQ_box,  "FGCOLOR*:5", FG_Colour_Not_Complete)

		-- Need to keep track of multiple achievements for SQ in Zones. Index them by zone LineColumn.

		local ccount, count
		-- Set up box with default data, and adjust
		for C=1, 4 do
			ccount = 0		-- per column
			for L = 1, 5 do
				key = tostring(L) .. tostring(C)	-- make name key
				dname = Locations[key]				-- Zone Locations
				if dname == nil then
					break	-- only 1 in Coldharbour
				end

				count = 0
				for _, id in ipairs (SQ_Info[key].quests) do	-- get the quests of the zone

					if  thischar.ach[id] ~= nil then	-- Have we got it?
						count =count +1
					end
				end
				ccount = ccount + count		-- Track the faction (Column)
				me.SQ_box:setcell(L,C,dname .. " (" .. tostring(count) .. ")")

				local colour = "FGCOLOR" .. L .. ":" .. C
				if count == #SQ_Info[key].quests then		-- Got them all??
					iup.SetAttribute(me.SQ_box, colour , FG_Colour_Complete)  -- Yup
				end
			end   -- L

			--Set Column Heading Colours
			if ccount >= 15 then
				iup.SetAttribute(me.SQ_box, "BGCOLOR0:" .. tostring(C), Colour_Heading_Complete)
			end
		end		-- C
---
-- Create SkillQuest Achievements Detail Boxes=======================

		me.SQ_Detail_box = {}
		me.SQ_Detail_Zbox = iup.zbox{}

		local  link
		for key, info in pairs(SQ_Info) do	-- for each zone
			me.SQ_Detail_box[key]= iup.matrix {numcol=2, numcol_visible=2,  numlin=0}

			local Line = 1
			me.SQ_Detail_box[key]:setcell(0,0, L.Ach_ID)
			me.SQ_Detail_box[key]:setcell(0,1, L.Name)
			me.SQ_Detail_box[key]:setcell(0,2, L.Link)
			iup.SetAttribute(me.SQ_Detail_box[key], "READONLY", "YES")
			iup.SetAttribute(me.SQ_Detail_box[key], "ALIGNMENT0", "ACENTER")
			iup.SetAttribute(me.SQ_Detail_box[key], "ALIGNMENTLIN0", "ALEFT")
			iup.SetAttribute(me.SQ_Detail_box[key], "ALIGNMENT1", "ALEFT")
			iup.SetAttribute(me.SQ_Detail_box[key], "ALIGNMENT2", "ALEFT")
			iup.SetAttribute(me.SQ_Detail_box[key],"WIDTH0", "30")
			iup.SetAttribute(me.SQ_Detail_box[key],"WIDTH1", "150")
			iup.SetAttribute(me.SQ_Detail_box[key],"WIDTH2", "250")
			for _, id in ipairs (info.quests) do	-- get the quests of the zone
				me.SQ_Detail_box[key].numlin = Line
				me.SQ_Detail_box[key]:setcell(Line,0, tostring(id))

				if Ach_Detail[id] == nil then
					name = "UNKN"
				else
					name = Ach_Detail[id].name
				end
				link = SQ_dat[id].link1
				me.SQ_Detail_box[key]:setcell(Line,1, name)
				me.SQ_Detail_box[key]:setcell(Line,2, link)
				-- Set Detail Colours on achievement
				if thischar.ach[id] == nil  then
					iup.SetAttribute(me.SQ_Detail_box[key],"FGCOLOR" .. tostring(Line) .. ":*", FG_Colour_Not_Complete)	-- Nope
				end

				Line= Line+1
			end
		-- Click on Link,
		local thisSQDetail = me.SQ_Detail_box[key]	-- The function def below doesn't like the [key]
		function thisSQDetail:click_cb(L,C)
				if C == 2 then
					iup.Help(self:getcell(L,C))		-- Launch Browser
				else
					return IUP_IGNORE
				end
			end

			iup.Append(me.SQ_Detail_Zbox, me.SQ_Detail_box[key])
		end

		function me.SQ_box:enteritem_cb(L,C)
			me.SQ_Detail_Zbox.value = me.SQ_Detail_box[tostring(L) .. tostring(C)]
		end
--========== DLC

		me.DLC_box= iup.matrix {numcol=3, numcol_visible=3,  numlin=4, widthdef=105}
		iup.SetAttribute(me.DLC_box, "READONLY", "YES")
		me.DLC_box.dat = DLC_Dat
		me.DLC_box.mousemove_cb = box_mousemove_cb
		me.DLC_box.leavewindow_cb = box_leavewindow_cb
		--Set Column titles

		me.DLC_box:setcell(0,1, DLC_names[1].long)	-- Orsinium
		me.DLC_box:setcell(0,2, DLC_names[3].long)	-- IC
		me.DLC_box:setcell(0,3, DLC_names[4].long)	-- Hist

		for id,_ in pairs (DLC_Dat.id) do
				local L = DLC_Dat.id[id].L
				local C = DLC_Dat.id[id].C
				local key = tostring(L).. tostring(C)	-- make name key
				me.DLC_box:setcell(L, C, DLC_Location_names[key])
		end


		-- set text to black and bg to green if achievement found.
		for id,_ in pairs (DLC_Dat.id) do
			local bgcolour = "BGCOLOR" .. DLC_Dat.id[id].L .. ":" .. DLC_Dat.id[id].C
			if thischar.ach[id] ~= nil then
				iup.SetAttribute(me.DLC_box, bgcolour, BG_Colour_Complete)
				-- Add char to dungeon
				key = tostring(DLC_Dat.id[id].L .. DLC_Dat.id[id].C)
				dung.DLC.key[key][playerID] = true
			else
				iup.SetAttribute(me.DLC_box, bgcolour, BG_Colour_Not_Complete)
			end
		end

		if thischar.ach[1248] ~= nil then  --"Hero of Wrothgar",
				iup.SetAttribute(me.DLC_box,  "BGCOLOR0:1", Colour_Heading_Complete)
		end

	 -- ====================================
	--  == Prepare for the character data display tabs
		me.tab = iup.vbox{
					["tabtitle"] = me.name,		-- This vbox will be a tab and the tab text is this

					iup.hbox{		--Top Information bar
							Alignment = "ACENTER",
							iup.label{title=thischar.world,PADDING="10X0"},
							iup.label{title=me.gender, FONT="Times,BOLD,10"},
							iup.label{title=thischar.Race .." / ".. thischar.Class, PADDING="10X0", FONT="Times,BOLD,10"},
							iup.label{title=thischar.Alliance, PADDING="10X0"},
							iup.label{title=L.Level .. ": ".. me.levelstr, PADDING="10X0"},
							iup.label{title=L.Created .. os.date(dateformat,thischar.Created), PADDING="10X0"},
							iup.label{title=L.LLog .. os.date(dateformat,thischar.LoginTime), PADDING="10X0"},
							iup.label{title=L.TPlayed .. me.timeplayed .." " .. L.Hrs},
							iup.fill{}
							},
					iup.label{SEPARATOR="HORIZONTAL"}
					}

		me.data_tabs = iup.tabs{} --Data tabs for Char
		-- All Grp Dungeons
		for _,i in ipairs (Grp_Order) do
			if me.isvet or me.Grp[i].vet == false then
				-- non vet chars only see non-vet dungeons
				iup.Append(me.data_tabs, me.Grp[i].tab)
			end
		end

		-- All Craglorn Dungeons
		for _,i in ipairs (Craglorn_Order) do
			if me.isvet or me.Craglorn[i].vet == false then
				-- non vet chars only see non-vet dungeons
				iup.Append(me.data_tabs, me.Craglorn[i].tab)
			end
		end

		iup.Append(me.data_tabs,	iup.vbox {	["tabtitle"] =L.PubDungeon,
												iup.label{title=L.PubLab,expand="HORIZONTAL"},
												me.Pub_box,
												iup.fill{}
											})
		if me.isvet then
		--[[
		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.VetDungeon,
												iup.label{title=L.VetLab,expand="HORIZONTAL"},
												me.Vet_box,
												iup.fill{}
											})

--]]
		end

		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.Leveling,
										--		iup.label{title="LevLabel",expand="HORIZONTAL"},
												me.leveling_box,
												iup.fill{}
											})

		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.Locations,
											--	iup.label{title="LevLabel",expand="HORIZONTAL"},
												me.Map_box,
												iup.fill{}
											})

		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.WBosses,
												iup.label{title=L.WBLab,expand="HORIZONTAL"},
												me.WB_box,
												iup.fill{}
											})

		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.SkillQuests,
												iup.label{title=L.SkillLab,expand="HORIZONTAL"},
												me.SQ_box,
												iup.label{title=L.Detail},
												me.SQ_Detail_Zbox,
												iup.fill{}
											})
		iup.Append(me.data_tabs, iup.vbox {	["tabtitle"] =L.DLC,
												iup.label{title=L.DLCLab,expand="HORIZONTAL"},
												me.DLC_box,
												iup.fill{}
											})


		iup.Append(me.tab,me.data_tabs)

		iup.Append(accounts[acc].char_tabs,me.tab)

		local wide =(((#accounts[acc].playerIDs+1) * 110)+10)
		if wide < 680  then
			wide = 680
		elseif wide >950 then
		--	panel = 1600
		end

		accounts[acc].panelsize =  tostring(wide) ..  "x310"
	end  -- Chars

-- Add to end of Characters
iup.Append(accounts[acc].char_tabs, accounts[acc].log_tab)

--=================  END OF CHARACTER MODE DISPLAY
--=================  START OF DUNGEON MODE DISPLAY

   -- Generic function for populating these tables
	populate = function(ADung,Grp_key)
		for line, key in ipairs(Grp_key) do  -- for lines going down, get the key
		-- does that char exist in the table. Check by PlayerID
			for col,playerID in ipairs(accounts[acc].playerIDs) do	-- over each char in order
				if ADung.key[key][playerID]  then
					ADung.box:setcell(line,col, L.YesLabel)
					iup.SetAttribute(ADung.box,"BGCOLOR" .. tostring(line) .. ":" .. tostring(col), BG_Colour_Complete)
				else
					ADung.box:setcell(line,col, L.NoLabel)
					iup.SetAttribute(ADung.box,"BGCOLOR" .. tostring(line) .. ":" .. tostring(col), BG_Colour_Not_Complete)
				end
			end
		end
	end

	-- Create Pub Dungeon Character Box=========================

	dung.pub.box = iup.matrix {numcol=#accounts[acc].playerIDs,  numlin=#Pub_Dat.key, widthdef=100}
	dung.pub.box.dat = Pub_Dat
	dung.pub.box.mousemove_cb = box_mousemove_cb
	dung.pub.box.leavewindow_cb = box_leavewindow_cb

	--Set Line titles
	for line,key in ipairs(Pub_Dat.key) do
		dung.pub.box:setcell(line, 0, pub_names[key])
	end
	--set lines
	dung.pub.box:setcell(0,0, L.Location)

	--Create Columns for Chars
	for col ,playerID in ipairs(accounts[acc].playerIDs) do
		dung.pub.box:setcell(0, col, playerNames[playerID])
	end

	iup.SetAttribute(dung.pub.box, "READONLY", "YES")

	-- Populate with character data ============================
	populate(dung.pub,Pub_Dat.key)

	-- Create Pub Dungeon Tab ==================================

	dung.pub.tab = iup.vbox {
						["tabtitle"] =L.Pub,
						dung.pub.box,
						iup.fill{},
				}

	iup.Append(accounts[acc].dung_tabs, dung.pub.tab)

	-- Grp Dungeons  ===========================================

	for _,i in ipairs (Grp_Order) do
		iup.Append(accounts[acc].dung_tabs, dung.Grp[i].tab)
		-- Populate with character data ============================
		populate(dung.Grp[i], Grp_Dat[i].key)
	end

	-- Create DLC Dungeon Character Box=========================

	dung.DLC.box = iup.matrix {numcol=#accounts[acc].playerIDs ,  numlin=#DLC2key, widthdef=100}

	dung.DLC.box.dat = DLC_Dat
	dung.DLC.box.mousemove_cb = box_mousemove_cb
	dung.DLC.box.leavewindow_cb = box_leavewindow_cb

	--Set Line titles
	for i, key in ipairs(DLC2key) do
		dung.DLC.box:setcell(i, 0, DLC_Location_names[key])
	end
	--set lines
	dung.DLC.box:setcell(0,0, L.Location)
	--Create Columns for Chars
	for i,playerID in ipairs(accounts[acc].playerIDs ) do
		dung.DLC.box:setcell(0, i, playerNames[playerID])
	end

	iup.SetAttribute(dung.DLC.box, "READONLY", "YES")

	-- Populate with character data ============================
	for line,key in ipairs(DLC2key) do		-- over each dungeon
	    -- does that char exist in the table.
		for i,playerID in ipairs(accounts[acc].playerIDs ) do	-- over each char in order
			if dung.DLC.key[key][playerID] == nil then
				dung.DLC.box:setcell(line,i, "N")
				iup.SetAttribute(dung.DLC.box,"BGCOLOR" .. tostring(line) .. ":" .. tostring(i), BG_Colour_Not_Complete)
			else
				dung.DLC.box:setcell(line,i, "Y")
				iup.SetAttribute(dung.DLC.box,"BGCOLOR" .. tostring(line) .. ":" .. tostring(i), BG_Colour_Complete)
			end
		end
	end


	-- Create DLC Dungeon Tab ==================================
	dung.DLC.tab = iup.vbox {
						["tabtitle"] =L.DLC,
						dung.DLC.box,
						iup.fill{},
				}
	iup.Append(accounts[acc].dung_tabs, dung.DLC.tab)



	if #accounts[acc].playerIDs_vet > 0  then  -- skip vet and trials if no eligible chars

		-- Create Craglorn  Tab ============================================
		for _,i in ipairs (Craglorn_Order) do
			iup.Append(accounts[acc].dung_tabs, dung.Craglorn[i].tab)
			-- Populate with character data ============================
			populate(dung.Craglorn[i], Craglorn_Dat[i].key)
		end
	end -- has vet chars

end -- Accounts

table.sort(accounts_list)

function select_account()
	local selected
		if #accounts_list > 1 then
			selected = iup.ListDialog (1, L.SelectA,
					#accounts_list,	--Size
					accounts_list,
					1, --Initial
					1,#accounts_list	--MaxCol MaxLine
					)

			if selected <0 then
				return nil		-- Cancelled
			else
				return accounts_list[selected+1]
			end
		else
		return accounts_list[1]		-- only 1 account, no need for Dialog
		end
end


-- Create dialog to choose account
myaccount=select_account()


if myaccount ~=nil then
	-- Create dialog if not cancelled
	dlg = iup.dialog{iup.vbox{
							accounts[myaccount].mode,
							accounts[myaccount].mode_zbox,
							detail_name,		-- Hover over information
							detail_desc,
							Status_bar,	-- Bottom Status bar.
							margin="5x5",
							ngap="3",
							},
					title=L.title .. myaccount ,
					size=accounts[myaccount].panelsize,
					}
	-- Shows dialog in the centre of the screen
	dlg:showxy(iup.CENTER, iup.CENTER)

	if (iup.MainLoopLevel()==0) then
	  iup.MainLoop()
	end
end