--[[
Librarian is a library used to manage localization, packages, scripts, animations and data embedded
into the SVUI core addon.

It's main purpose is to keep all methods and logic needed to properly keep
core add-ins functioning outside of the core object.

It is also modifyiing LibStub to give me dominating control over which libraries are
allowed to be created and loaded regardless of versioning or timing.  

The reasoning for this is due to the potential for other addon to get loaded earlier
and embed newer versions of lib dependencies which can be devastating.                                                                   
--]]
local _G            = getfenv(0)
local select        = _G.select;
local assert        = _G.assert;
local type          = _G.type;
local error         = _G.error;
local pairs         = _G.pairs;
local next          = _G.next;
local ipairs        = _G.ipairs;
local loadstring    = _G.loadstring;
local setmetatable  = _G.setmetatable;
local rawset        = _G.rawset;
local rawget        = _G.rawget;
local tostring      = _G.tostring;
local tonumber      = _G.tonumber;
local tostring      = _G.tostring;
local xpcall        = _G.xpcall;
local table         = _G.table;
local tconcat       = table.concat;
local tremove       = table.remove;
local tinsert       = table.insert;
local strmatch      = _G.strmatch;
local table_sort    = table.sort;
local bit           = _G.bit;
local band          = bit.band;
local math          = _G.math;
local min,max,abs   = math.min,math.max,math.abs;
local LibStub = _G.LibStub;
local UIParent = _G.UIParent;
local GetScreenWidth = _G.GetScreenWidth;
local GetScreenHeight = _G.GetScreenHeight;
local IsAltKeyDown = _G.IsAltKeyDown;
--[[
The following are private and compressed versions of dependancy libraries                                                                  
--]]
local MAX_MINOR         = 999999999;
local geterrorhandler   = _G.geterrorhandler;
local CB_MAJOR          = "CallbackHandler-1.0";
local CB                = LibStub:NewLibrary(CB_MAJOR, MAX_MINOR, true)
local _CODE = [[
local next, xpcall, eh = ...
local method, ARGS
local function call() method(ARGS) end
local function dispatch(handlers, ...)
    local index
    index, method = next(handlers)
    if not method then return end
    local OLD_ARGS = ARGS
    ARGS = ...
    repeat
        xpcall(call, eh)
        index, method = next(handlers, index)
    until not method
    ARGS = OLD_ARGS
end
return dispatch
]];

local _META={__index=function(a,b)a[b]={}return a[b]end}
local function _err(a) return geterrorhandler()(a) end
local function _set(a)local b=_CODE;local c,d={},{}for e=1,a do c[e],d[e]="arg"..e,"old_arg"..e end;b=b:gsub("OLD_ARGS",tconcat(d,", ")):gsub("ARGS",tconcat(c,", "))return assert(loadstring(b,"safecall Dispatcher["..a.."]"))(next,xpcall,_err)end
local Dispatchers=setmetatable({},{__index=function(a,b)local c=_set(b)rawset(a,b,c)return c end})
function CB:New(a,b,c,d)b=b or"RegisterCallback"c=c or"UnregisterCallback"if d==nil then d="UnregisterAllCallbacks"end;local e=setmetatable({},_META)local registry={recurse=0,events=e}function registry:Fire(f,...)if not rawget(e,f)or not next(e[f])then return end;local g=registry.recurse;registry.recurse=g+1;Dispatchers[select('#',...)+1](e[f],f,...)registry.recurse=g;if registry.insertQueue and g==0 then for f,h in pairs(registry.insertQueue)do local i=not rawget(e,f)or not next(e[f])for j,k in pairs(h)do e[f][j]=k;if i and registry.OnUsed then registry.OnUsed(registry,a,f)i=nil end end end;registry.insertQueue=nil end end;a[b]=function(j,f,l,...)if type(f)~="string"then return end;l=l or f;local i=not rawget(e,f)or not next(e[f])if type(l)~="string"and type(l)~="function"then return end;local m;if type(l)=="string"then if type(j)~="table"or j==a or type(j[l])~="function"then return end;if select("#",...)>=1 then local n=select(1,...)m=function(...)j[l](j,n,...)end else m=function(...)j[l](j,...)end end else if type(j)~="table"and type(j)~="string"and type(j)~="thread"then return end;if select("#",...)>=1 then local n=select(1,...)m=function(...)l(n,...)end else m=l end end;if e[f][j]or registry.recurse<1 then e[f][j]=m;if registry.OnUsed and i then registry.OnUsed(registry,a,f)end else registry.insertQueue=registry.insertQueue or setmetatable({},_META)registry.insertQueue[f][j]=m end end;a[c]=function(j,f)if not j or j==a or type(f)~="string"then return end;if rawget(e,f)and e[f][j]then e[f][j]=nil;if registry.OnUnused and not next(e[f])then registry.OnUnused(registry,a,f)end end;if registry.insertQueue and rawget(registry.insertQueue,f)and registry.insertQueue[f][j]then registry.insertQueue[f][j]=nil end end;if d then a[d]=function(...)if select("#",...)<1 or select("#",...)==1 and...==a then return end;for o=1,select("#",...)do local j=select(o,...)if registry.insertQueue then for f,h in pairs(registry.insertQueue)do if h[j]then h[j]=nil end end end;for f,h in pairs(e)do if h[j]then h[j]=nil;if registry.OnUnused and not next(h)then registry.OnUnused(registry,a,f)end end end end end end;return registry end

local LSM_MAJOR = "LibSharedMedia-3.0";
local LSM = LibStub:NewLibrary(LSM_MAJOR, MAX_MINOR, true)
if(LSM) then
    local locale=GetLocale()local b;local c=0;
    LSM.LOCALE_BIT_koKR=1;LSM.LOCALE_BIT_ruRU=2;LSM.LOCALE_BIT_zhCN=4;LSM.LOCALE_BIT_zhTW=8;LSM.LOCALE_BIT_western=128;LSM.callbacks=LSM.callbacks or CB:New(LSM)LSM.DefaultMedia=LSM.DefaultMedia or{}LSM.MediaList=LSM.MediaList or{}LSM.MediaTable=LSM.MediaTable or{}LSM.MediaType=LSM.MediaType or{}LSM.OverrideMedia=LSM.OverrideMedia or{}LSM.MediaType.BACKGROUND="background"LSM.MediaType.BORDER="border"LSM.MediaType.FONT="font"LSM.MediaType.STATUSBAR="statusbar"LSM.MediaType.SOUND="sound"if not LSM.MediaTable.background then LSM.MediaTable.background={}end;LSM.MediaTable.background["Blizzard Dialog Background"]=[[Interface\DialogFrame\UI-DialogBox-Background]]LSM.MediaTable.background["Blizzard Dialog Background Dark"]=[[Interface\DialogFrame\UI-DialogBox-Background-Dark]]LSM.MediaTable.background["Blizzard Dialog Background Gold"]=[[Interface\DialogFrame\UI-DialogBox-Gold-Background]]LSM.MediaTable.background["Blizzard Low Health"]=[[Interface\FullScreenTextures\LowHealth]]LSM.MediaTable.background["Blizzard Marble"]=[[Interface\FrameGeneral\UI-Background-Rock]]LSM.MediaTable.background["Blizzard Out of Control"]=[[Interface\FullScreenTextures\OutOfControl]]LSM.MediaTable.background["Blizzard Parchment"]=[[Interface\AchievementFrame\UI-Achievement-Parchment-Horizontal]]LSM.MediaTable.background["Blizzard Parchment 2"]=[[Interface\AchievementFrame\UI-GuildAchievement-Parchment-Horizontal]]LSM.MediaTable.background["Blizzard Rock"]=[[Interface\FrameGeneral\UI-Background-Rock]]LSM.MediaTable.background["Blizzard Tabard Background"]=[[Interface\TabardFrame\TabardFrameBackground]]LSM.MediaTable.background["Blizzard Tooltip"]=[[Interface\Tooltips\UI-Tooltip-Background]]LSM.MediaTable.background["Solid"]=[[Interface\Buttons\WHITE8X8]]if not LSM.MediaTable.border then LSM.MediaTable.border={}end;LSM.MediaTable.border["None"]=[[Interface\None]]LSM.MediaTable.border["Blizzard Achievement Wood"]=[[Interface\AchievementFrame\UI-Achievement-WoodBorder]]LSM.MediaTable.border["Blizzard Chat Bubble"]=[[Interface\Tooltips\ChatBubble-Backdrop]]LSM.MediaTable.border["Blizzard Dialog"]=[[Interface\DialogFrame\UI-DialogBox-Border]]LSM.MediaTable.border["Blizzard Dialog Gold"]=[[Interface\DialogFrame\UI-DialogBox-Gold-Border]]LSM.MediaTable.border["Blizzard Party"]=[[Interface\CHARACTERFRAME\UI-Party-Border]]LSM.MediaTable.border["Blizzard Tooltip"]=[[Interface\Tooltips\UI-Tooltip-Border]]if not LSM.MediaTable.font then LSM.MediaTable.font={}end;local d=LSM.MediaTable.font;if locale=="koKR"then c=LSM.LOCALE_BIT_koKR;d["굵은 글꼴"]=[[Fonts\2002B.TTF]]d["기본 글꼴"]=[[Fonts\2002.TTF]]d["데미지 글꼴"]=[[Fonts\K_Damage.TTF]]d["퀘스트 글꼴"]=[[Fonts\K_Pagetext.TTF]]LSM.DefaultMedia["font"]="기본 글꼴"elseif locale=="zhCN"then c=LSM.LOCALE_BIT_zhCN;d["伤害数字"]=[[Fonts\ARKai_DB.ttf]]d["默认"]=[[Fonts\ARKai_T.ttf]]d["聊天"]=[[Fonts\ARHei.ttf]]LSM.DefaultMedia["font"]="默认"elseif locale=="zhTW"then c=LSM.LOCALE_BIT_zhTW;d["提示訊息"]=[[Fonts\bHEI00M.ttf]]d["聊天"]=[[Fonts\bHEI01B.ttf]]d["傷害數字"]=[[Fonts\bKAI00M.ttf]]d["預設"]=[[Fonts\bLEI00D.ttf]]LSM.DefaultMedia["font"]="預設"elseif locale=="ruRU"then c=LSM.LOCALE_BIT_ruRU;d["Arial Narrow"]=[[Fonts\ARIALN.TTF]]d["Nimrod MT"]=[[Fonts\NIM_____.ttf]]LSM.DefaultMedia.font="Arial Narrow"else c=LSM.LOCALE_BIT_western;b=true;d["Arial Narrow"]=[[Fonts\ARIALN.TTF]]d["Friz Quadrata TT"]=[[Fonts\FRIZQT__.TTF]]d["Morpheus"]=[[Fonts\MORPHEUS.TTF]]d["Skurri"]=[[Fonts\SKURRI.TTF]]LSM.DefaultMedia.font="Arial Narrow"end;if not LSM.MediaTable.statusbar then LSM.MediaTable.statusbar={}end;LSM.MediaTable.statusbar["Blizzard"]=[[Interface\TargetingFrame\UI-StatusBar]]LSM.MediaTable.statusbar["Blizzard Character Skills Bar"]=[[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]]LSM.DefaultMedia.statusbar="Blizzard"if not LSM.MediaTable.sound then LSM.MediaTable.sound={}end;LSM.MediaTable.sound["None"]=[[Interface\Quiet.ogg]]LSM.DefaultMedia.sound="None"local e=LSM.DefaultMedia;local f=LSM.MediaList;local g=LSM.MediaTable;local h=LSM.OverrideMedia;local function i(j)local k=g[j]if not k then return end;if not f[j]then f[j]={}end;local l=f[j]local m=0;for n in pairs(k)do m=m+1;l[m]=n end;table_sort(l)end;
    function LSM:Register(j,o,p,q)if type(j)~="string"then error(LSM_MAJOR..":Register(mediatype, key, data, langmask) - mediatype must be string, got "..type(j))end;if type(o)~="string"then error(LSM_MAJOR..":Register(mediatype, key, data, langmask) - key must be string, got "..type(o))end;j=j:lower()if j==LSM.MediaType.FONT and q and band(q,c)==0 or not(q or b)then return false end;if not g[j]then g[j]={}end;local k=g[j]if k[o]then return false end;k[o]=p;i(j)self.callbacks:Fire("LibSharedMedia_Registered",j,o)return true end;
    function LSM:Fetch(j,o,r)local s=g[j]local t=h[j]local u=s and t and s[t]or s[o]or not r and e[j]and s[e[j]]or nil;return u end;
    function LSM:IsValid(j,o)return g[j]and not o or g[j][o]and true or false end;
    function LSM:HashTable(j)return g[j]end;
    function LSM:List(j)if not g[j]then return nil end;if not f[j]then i(j)end;return f[j]end;
    function LSM:GetGlobal(j)return h[j]end;
    function LSM:SetGlobal(j,o)if not g[j]then return false end;h[j]=o and g[j][o]and o or nil;self.callbacks:Fire("LibSharedMedia_SetGlobal",j,h[j])return true end;
    function LSM:GetDefault(j)return e[j]end;
    function LSM:SetDefault(j,o)if g[j]and g[j][o]and not e[j]then e[j]=o;return true else return false end end
end

local WINDOW_MAJOR = "LibWindow-1.1";
local WINDOW = LibStub:NewLibrary(WINDOW_MAJOR, MAX_MINOR, true);
if(WINDOW) then
    WINDOW.utilFrame = WINDOW.utilFrame or CreateFrame("Frame")
    WINDOW.delayedSavePosition = WINDOW.delayedSavePosition or {}
    WINDOW.windowData = WINDOW.windowData or {} 
    WINDOW.embeds = WINDOW.embeds or {}
    local mixins = {}
    local function a(b,c)local names=WINDOW.windowData[b].names;if names then if names[c]then return names[c]end;if names.prefix then return names.prefix..c end end;return c end;
    local function d(b,c,e)WINDOW.windowData[b].storage[a(b,c)]=e end;
    local function f(b,c)return WINDOW.windowData[b].storage[a(b,c)]end;
    WINDOW.utilFrame:SetScript("OnUpdate",function(g)g:Hide()for b,h in pairs(WINDOW.delayedSavePosition)do WINDOW.delayedSavePosition[b]=nil;WINDOW.SavePosition(b)end end)
    local function i(b)WINDOW.delayedSavePosition[b]=true;WINDOW.utilFrame:Show()end;
    mixins["RegisterConfig"]=true;
    function WINDOW.RegisterConfig(b,storage,names)if not WINDOW.windowData[b]then WINDOW.windowData[b]={}end;WINDOW.windowData[b].names=names;WINDOW.windowData[b].storage=storage end;local j={GetWidth=function()return GetScreenWidth()*UIParent:GetScale()end,GetHeight=function()return GetScreenHeight()*UIParent:GetScale()end,GetScale=function()return 1 end}mixins["SavePosition"]=true;
    function WINDOW.SavePosition(b)local k=b:GetParent()if not k then k=j elseif k~=UIParent then return end;local l=b:GetScale()local m,n=b:GetLeft()*l,b:GetTop()*l;local o,p=b:GetRight()*l,b:GetBottom()*l;local q,r=k:GetWidth(),k:GetHeight()local s,t,u;if m<q-o and m<abs((m+o)/2-q/2)then s=m;u="LEFT"elseif q-o<abs((m+o)/2-q/2)then s=o-q;u="RIGHT"else s=(m+o)/2-q/2;u=""end;if p<r-n and p<abs((p+n)/2-r/2)then t=p;u="BOTTOM"..u elseif r-n<abs((p+n)/2-r/2)then t=n-r;u="TOP"..u else t=(p+n)/2-r/2 end;if u==""then u="CENTER"end;d(b,"x",s)d(b,"y",t)d(b,"point",u)d(b,"scale",l)b:ClearAllPoints()b:SetPoint(u,b:GetParent(),u,s/l,t/l)end;mixins["RestorePosition"]=true;
    function WINDOW.RestorePosition(b)local s=f(b,"x")local t=f(b,"y")local u=f(b,"point")local l=f(b,"scale")if l then (b.lw11origSetScale or b.SetScale)(b,l)else l=b:GetScale()end;if not s or not t then s=0;t=0;u="CENTER"end;s=s/l;t=t/l;b:ClearAllPoints()if not u and t==0 then u="CENTER"end;if not u then b:SetPoint("TOPLEFT",b:GetParent(),"BOTTOMLEFT",s,t)i(b)return end;b:SetPoint(u,b:GetParent(),u,s,t)end;mixins["SetScale"]=true;
    function WINDOW.SetScale(b,v)d(b,"scale",v)(b.lw11origSetScale or b.SetScale)(b,v)WINDOW.RestorePosition(b)end;
    function WINDOW.OnDragStart(b)WINDOW.windowData[b].isDragging=true;b:StartMoving()end;
    function WINDOW.OnDragStop(b)b:StopMovingOrSizing()WINDOW.SavePosition(b)WINDOW.windowData[b].isDragging=false;if WINDOW.windowData[b].altEnable and not IsAltKeyDown()then b:EnableMouse(false)end end;local function w(...)return WINDOW.OnDragStart(...)end;
    local function x(...)return WINDOW.OnDragStop(...)end;mixins["MakeDraggable"]=true;
    function WINDOW.MakeDraggable(b)assert(WINDOW.windowData[b])b:SetMovable(true)b:SetScript("OnDragStart",w)b:SetScript("OnDragStop",x)b:RegisterForDrag("LeftButton")end;
    function WINDOW.OnMouseWheel(b,y)local v=f(b,"scale")if y<0 then v=max(v*0.9,0.1)else v=min(v/0.9,3)end;WINDOW.SetScale(b,v)end;
    local function z(...)return WINDOW.OnMouseWheel(...)end;
    mixins["EnableMouseWheelScaling"]=true;
    function WINDOW.EnableMouseWheelScaling(b)b:SetScript("OnMouseWheel",z)end;WINDOW.utilFrame:SetScript("OnEvent",function(g,A,B,C)if A=="MODIFIER_STATE_CHANGED"then if B=="LALT"or B=="RALT"then for b,h in pairs(WINDOW.altEnabledFrames)do if not WINDOW.windowData[b].isDragging then b:EnableMouse(C==1)end end end end end)mixins["EnableMouseOnAlt"]=true;
    function WINDOW.EnableMouseOnAlt(b)assert(WINDOW.windowData[b])WINDOW.windowData[b].altEnable=true;b:EnableMouse(not not IsAltKeyDown())if not WINDOW.altEnabledFrames then WINDOW.altEnabledFrames={}WINDOW.utilFrame:RegisterEvent("MODIFIER_STATE_CHANGED")end;WINDOW.altEnabledFrames[b]=true end;
    function WINDOW:Embed(D)if not D or not D[0]or not D.GetObjectType then error("Usage: WINDOW:Embed(frame)",1)end;D.lw11origSetScale=D.SetScale;for c,h in pairs(mixins)do D[c]=self[c]end;WINDOW.embeds[D]=true;return D end;for D,h in pairs(WINDOW.embeds)do WINDOW:Embed(D)end
end