
showBackgroundChecked = true;
openInspectChecked = true;

local unitid = nil;
local frameBorderSize = 18;
local mouseFacing = 0;
local cursorX = 0;
local cursorY = 0;

local backFile = "Interface\\Glues\\LoadingScreens\\LoadScreenZulGurub"
local backNone = "Interface\\DialogFrame\\UI-DialogBox-Background"; -- "Interface\\Tooltips\\UI-Tooltip-Background";
local edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border"; -- "Interface\\Tooltips\\UI-Tooltip-Border";
local backdrop = {
    bgFile = backFile,
    edgeFile = edgeFile,
    tile = false, tileSize = 16, edgeSize = 24,
    insets = { left = 8, right = 8, top = 8, bottom = 8 }
}

-----------------------
-- KEYBOARD BINDINGS
-----------------------
BINDING_HEADER_MODELVIEWER = "Model Viewer"
BINDING_NAME_MODELVIEWER_VIEWMODEL = "View Model"

function ModelViewerMainFrame_OnLoad(self)
    ModelViewerMainFrame:RegisterEvent("VARIABLES_LOADED");
    ModelViewerMainFrame:RegisterEvent("PLAYER_TARGET_CHANGED");

    ModelViewerMainFrame:RegisterForDrag("LeftButton", "RightButton");

    ModelViewerMainFrame:SetScript("OnEvent", function(self, event, ...) ModelViewerMainFrame_OnEvent(self, event, ...); end);
    ModelViewerMainFrame:SetScript("OnUpdate", function(self, event, ...) ModelViewerMainFrame_OnUpdate(self, event, ...); end);
    ModelViewerMainFrame:SetScript("OnMouseUp", function(self, button) ModelViewerMainFrame_OnMouseUp(self, button); end);
    ModelViewerMainFrame:SetScript("OnMouseDown", function(self, button) ModelViewerMainFrame_OnMouseDown(self, button); end);
    ModelViewerMainFrame:SetScript("OnDragStart", function() ModelViewerMainFrame_OnDragStart(); end);
    ModelViewerMainFrame:SetScript("OnDragStop", function() ModelViewerMainFrame_OnDragStop(); end);

    tinsert(UISpecialFrames, "ModelViewerMainFrame"); -- Hide by ESC Key.
    tinsert(UISpecialFrames, "ModelViewerConfigFrame"); -- Hide by ESC Key.
end

function ModelViewerMainFrame_OnEvent(self, event, ...)
    if (event == "VARIABLES_LOADED") then
        ModelViewerMainFrame_OnVariablesLoaded();
    elseif (event == "PLAYER_TARGET_CHANGED") then
        ModelViewerMainFrame_SetUnit();
    end
end

function ModelViewerMainFrame_SetUnit()    
    --unitid = nil;
    if (UnitExists("target")) then
        unitid = "target";
        ModelViewerMainFrame_PlayerModel:SetUnit(unitid);

        if ModelViewerMainFrame_PlayerModel:IsVisible() then
            UnitInfoLayer_Show();
            BlizzardInspectUI_Show();
        end
    else 
        --ModelViewerMainFrame_Hide();
    end
end

function ModelViewerFrame_ViewModel_OnPress()
    if (ModelViewerMainFrame:IsVisible()) then
    --if (DressUpFrame:IsVisible()) then
        ModelViewerMainFrame_Hide();
    else
        if (not UnitExists("target")) then
            unitid = "player";
            ModelViewerMainFrame_PlayerModel:SetUnit(unitid);
        end
        ModelViewerMainFrame_Show();
    end
end

function ModelViewerMainFrame_OnMouseDown(self, button)
    cursorX, cursorY = GetCursorPosition();

    if (button == "LeftButton") then
        mouseFacing = 1; -- Model Rotation Start.
    end
end

function ModelViewerMainFrame_OnMouseUp(self, button)
    local cx, cy = GetCursorPosition();
    if cursorX == cx and cursorY == cy then
        ModelViewerMainFrame_Hide();
    end
    mouseFacing = 0; -- Model Rotation End.
end

function ModelViewerMainFrame_OnDragStart()

end

function ModelViewerMainFrame_OnDragStop()
    mouseFacing = 0; -- Model Rotation End.
end

function ModelViewerMainFrame_OnUpdate()
    -------------------------------
    -- Update Model Rotation.
    -------------------------------
    if (mouseFacing == 1) then
        local cx, cy = GetCursorPosition();
        ModelViewerMainFrame_PlayerModel:SetFacing(ModelViewerMainFrame_PlayerModel:GetFacing() + ((cx - cursorX) / 50));
        cursorX, cursorY = GetCursorPosition();
    end
end

function ModelViewerMainFrame_Show()
    if (unitid == nil) then
        return;
    end

    PlaySound("GAMEDIALOGOPEN", "master"); -- http://wowwiki.wikia.com/wiki/API_PlaySound    

    --backdrop.bgFile = classFileName;
    --ModelViewerMainFrame:SetBackdrop(backdrop)

    local scale = UIParent:GetEffectiveScale();
    local width = GetScreenWidth() * scale;
    local height = GetScreenHeight() * scale;

    width = width - (width / 2.7);
    height = height - (height / 8);

    local frame = ModelViewerMainFrame;
    local model = ModelViewerMainFrame_PlayerModel;

    frame:SetWidth(width);
    frame:SetHeight(height);
    frame:ClearAllPoints();
    frame:SetPoint("CENTER", "UIParent");

    if (showBackgroundChecked) then
        ModelViewerMainFrame_ShowBackground();
    else
        ModelViewerMainFrame_HideBackground();
    end
    ShowUIPanel(frame);
    --frame:SetFrameStrata(largeWinStrata);

    --------------
    -- 모델 설정
    --------------
    width = height;
    mouseFacing = 0; -- Model Rotation End.
    model:SetFacing(mouseFacing);
    --model:SetAnimation(26, 0); -- http://us.battle.net/forums/en/wow/topic/8569600188
    model:SetWidth(width - frameBorderSize);
    model:SetHeight(height - frameBorderSize);
    ShowUIPanel(model);
    
    UnitInfoLayer_Show();
    BlizzardInspectUI_Show();
end

function ModelViewerMainFrame_Hide()
    if ModelViewerMainFrame:IsVisible() then
        PlaySound("GAMEDIALOGCLOSE", "master"); -- http://wowwiki.wikia.com/wiki/API_PlaySound
    end

    HideUIPanel(ModelViewerMainFrame_PlayerModel);
    HideUIPanel(ModelViewerMainFrame);
    if (ModelViewerConfigFrame:IsVisible()) then
        HideUIPanel(ModelViewerConfigFrame);
    end
    BlizzardInspectUI_Hide();
end

function UnitInfoLayer_Show()

    local name, realm = UnitName(unitid);

    if (unitid ~= nil and name ~= nil) then

        local level = UnitLevel(unitid);
        local factionGroup, factionName = UnitFactionGroup(unitid);

        if (factionGroup ~= nil) then
            --------------
            -- FACTION
            --------------
            --print("factionGroup: "..factionGroup); -- "Horde", "Alliance" or "Neutral"
            --print("factionName: "..factionName); -- "호드", "얼라이언스"

            local factionTexture = "Interface\\AddOns\\ModelViewer\\Textures\\"..factionGroup..".tga";
            --local factionTexture = "Interface\\PvPRankBadges\\PvPRank"..factionGroup..".blp";
            ModelViewerMainFrame_FactionTexture:SetTexture(factionTexture);
            ModelViewerMainFrame_FactionTexture:Show();

            if factionName == nil then
                factionName = UnitCreatureType(unitid);
            end
            if UnitIsEnemy("player", unitid) then
                ModelViewerMainFrame_FactionString:SetTextColor(1, 0, 0, 1); -- Red
            else
                ModelViewerMainFrame_FactionString:SetTextColor(0, 1, 0, 1); -- Green
            end
            ModelViewerMainFrame_FactionString:SetText(factionName);
            ModelViewerMainFrame_FactionString:Show();

            --------------
            -- NAME
            --------------
            ModelViewerMainFrame_NameString:SetText(name);
            ModelViewerMainFrame_NameString:Show();

            --------------
            -- LEVEL
            --------------
            ModelViewerMainFrame_LevelString:SetText("Level "..level);
            ModelViewerMainFrame_LevelString:Show();

            ModelViewerMainFrame_NoNameString:Hide();
            ModelViewerMainFrame_NoLevelString:Hide();
        else
            ModelViewerMainFrame_FactionTexture:Hide();
            ModelViewerMainFrame_NameString:Hide();
            ModelViewerMainFrame_LevelString:Hide();
            ModelViewerMainFrame_FactionString:Hide();
            ModelViewerMainFrame_GuildString:Hide();

            --------------
            -- NAME
            --------------
            ModelViewerMainFrame_NoNameString:SetText(name);
            ModelViewerMainFrame_NoNameString:Show();

            --------------
            -- LEVEL
            --------------
            ModelViewerMainFrame_NoLevelString:SetText("Level "..level);
            ModelViewerMainFrame_NoLevelString:Show();
        end

        --------------
        -- GUILD
        --------------
        local guildName, guildRankName, guildRankIndex = GetGuildInfo(unitid);
        if (guildName ~= nil) then
            ModelViewerMainFrame_GuildString:SetText(guildName);
            ModelViewerMainFrame_GuildString:Show();
        else
            ModelViewerMainFrame_GuildString:Hide();
        end

        --------------
        -- CLASS
        --------------
        local class, classFileName = UnitClass(unitid);
        local classColor = nil;
        if (class ~= nil and class ~= name) then
            --print("class: "..class); -- "마법사"
            --print("classFileName: "..classFileName); -- "MAGE"        
            local classTexture = "Interface\\AddOns\\ModelViewer\\Textures\\"..classFileName..".tga";
            ModelViewerMainFrame_ClassTexture:SetTexture(classTexture);
            ModelViewerMainFrame_ClassTexture:Show();

            classColor = RAID_CLASS_COLORS[classFileName];
            ModelViewerMainFrame_ClassString:SetText(class);
            ModelViewerMainFrame_ClassString:SetTextColor(classColor.r, classColor.g, classColor.b, 1);
            ModelViewerMainFrame_ClassString:Show();
        else
            ModelViewerMainFrame_ClassTexture:Hide();
            ModelViewerMainFrame_ClassString:Hide();
        end

        --------------
        -- RACE
        --------------
        local race, raceFileName = UnitRace(unitid);
        if (race ~= nil) then
            --print("race: "..race); -- "인간", "판다렌", ...
            --print("raceFileName: "..raceFileName); -- "Human", "Pandaren", ...

            if (raceFileName == "Scourge") then
                raceFileName = "Undead";
            end
            local raceTexture = "Interface\\AddOns\\ModelViewer\\Textures\\"..raceFileName..".tga";
            ModelViewerMainFrame_RaceTexture:SetTexture(raceTexture);
            ModelViewerMainFrame_RaceTexture:Show();

            if (classColor ~= nil) then
                ModelViewerMainFrame_RaceString:SetTextColor(classColor.r, classColor.g, classColor.b, 1);
            else
                ModelViewerMainFrame_RaceString:SetTextColor(0.9, 0.9, 0.9, 1);
            end
            ModelViewerMainFrame_RaceString:SetText(race);
            ModelViewerMainFrame_RaceString:Show();
        else
            ModelViewerMainFrame_RaceTexture:Hide();
            ModelViewerMainFrame_RaceString:Hide();
        end

        --local type = UnitCreatureType(unitid);
        --print("type: "..type); -- "인간형", "야수", "정령" ...

        --if UnitCreatureFamily(unitid) then
        --    print(UnitCreatureFamily(unitid));
        --end
        
        --if UnitClassification(unitid) then
        --    print(UnitClassification(unitid));
        --end
    end
end

function UnitInfoLayer_Hide()
    ModelViewerMainFrameStringName:Hide();
    ModelViewerMainFrameStringClass:Hide();
    ModelViewerMainFrameStringLevel:Hide();
    ModelViewerMainFrameStringFaction:Hide();
    ModelViewerMainFrameStringGuild:Hide();
end 

function ModelViewerMainFrame_ShowBackground()
    local frame = ModelViewerMainFrame;
    local max = table.getn(blps);
    local key = math.random (1, max);
    backdrop.bgFile = "Interface\\Glues\\LoadingScreens\\"..blps[key];
    --backdrop.bgFile = "Interface\\AddOns\\ModelViewer\\Textures\\Druid_Background.tga";
    backdrop.title = false;
    frame:SetBackdropColor(1, 1, 1, 0);
    frame:SetBackdrop(backdrop);
end

function ModelViewerMainFrame_HideBackground()
    local frame = ModelViewerMainFrame;
    backdrop.bgFile = backNone;
    backdrop.title = true;
    frame:SetBackdrop(backdrop);
    frame:SetBackdropColor(0, 0, 0, 0.9);
end

function BlizzardInspectUI_Show()
    if (openInspectChecked and CanInspect(unitid)) then
        InspectUnit(unitid);
    end
end

function BlizzardInspectUI_Hide()
    HideUIPanel(InspectFrame);
end

function ModelViewerMainFrame_ConfigButton_OnClick()
    ShowUIPanel(ModelViewerConfigFrame);
    --ModelViewerConfigFrame:Show();
end

function ModelViewerMainFrame_OnVariablesLoaded()
    showBackgroundChecked = ModelViewerSettings.showBackgroundChecked;
    openInspectChecked = ModelViewerSettings.openInspectChecked;
end

function ModelViewerMainFrame_SaveVariables()
    ModelViewerSettings = {
        showBackgroundChecked = showBackgroundChecked,
        openInspectChecked = openInspectChecked
    }
end

-- -----------------------------------------------------------------------------------------------
-- https://us.battle.net/support/en/article/download-the-world-of-warcraft-interface-addon-kit
-- -----------------------------------------------------------------------------------------------
blps = {
"LoadScreenArgentDungeon.blp",
"LOADSCREENARGENTRAID.BLP",
"LOADSCREENAUCHINDOUN.BLP",
"LOADSCREENAZJOLNERUB76.BLP",
"LoadScreenAzjolUpperCity.blp",
"LoadScreenBaradinHold.blp",
"LoadScreenBlackrockCaverns.blp",
"LoadScreenBlackrockDepths.blp",
"LoadScreenBlackwingDescentRaid.blp",
"LoadScreenBlackWingLair.blp",
"LoadScreenBladesEdgeArena.blp",
"LoadScreenCave.blp",
"LOADSCREENCAVERNSTIME.BLP",
"LoadScreenChamberBlack.blp",
"LoadScreenChampionsHall.blp",
"LoadScreenDalaranPrison.blp",
"LoadScreenDalaranSewersArena.blp",
"LoadScreenDeadmines.blp",
"LOADSCREENDEATHKNIGHT.BLP",
"LoadScreenDeepholm.blp",
"LOADSCREENDEEPHOLMDUNGEON.BLP",
"LoadScreenDireMaul.blp",
"LoadScreenDrakTharon.blp",
"LoadScreenDungeon.blp",
"LoadScreenEnviroment.blp",
"LoadScreenGilneasBG.blp",
"LoadScreenGilneasBG2.blp",
"LoadScreenGnomeregan.blp",
"LOADSCREENGRIMBATOL.BLP",
"LoadScreenGrimBatolRaid.blp",
"LOADSCREENGUNDRAK.BLP",
"LoadScreenHallofLegends.blp",
"LoadScreenHallsofOrigination.blp",
"LoadScreenHallsofReflection.blp",
"LOADSCREENHELLFIRECITADEL5MAN.BLP",
"LOADSCREENHELLFIRECITADELRAID.BLP",
"LoadScreenHyjal.blp",
"LoadScreenIcecrown5man.blp",
"LoadScreenIcecrownCitadel.blp",
"LOADSCREENISLEOFCONQUEST.BLP",
"LoadScreenKarazhan.blp",
"LOADSCREENMALYGOS.BLP",
"LoadScreenMaraudon.blp",
"LoadScreenMoltenCore.blp",
"LoadScreenMonastery.blp",
"LoadScreenNagrandArenaBattlegrounds.blp",
"LoadScreenNexus70.blp",
"LoadScreenNexus80.blp",
"LoadScreenNorthrendBG.blp",
"LoadScreenOldStrathome.blp",
"LoadScreenOrgrimmarArena.blp",
"LoadScreenPitofSaron.blp",
"LoadScreenRagefireChasm.blp",
"LoadScreenRazorfenDowns.blp",
"LoadScreenRazorfenKraul.blp",
"LoadScreenRubySanctum.blp",
"LoadScreenRuinedCity.blp",
"LoadScreenRuinsofLordaeronBattlegrounds.blp",
"LoadScreenScholomance.blp",
"LOADSCREENSHADOWFANGKEEP.BLP",
"LoadScreenSkywall.blp",
"LoadScreenSkywallRaid.blp",
"LoadScreenStormwindStockade.blp",
"LoadScreenStrathome.blp",
"LoadScreenSunkenTemple.blp",
"LoadScreenSunwell5Man.blp",
"LOADSCREENTEMPESTKEEP.BLP",
"LoadScreenThroneoftheTides.blp",
"LoadScreenTolBarad.blp",
"LoadScreenTwinPeaksBG.blp",
"LOADSCREENULDAMAN.BLP",
"LoadScreenUlduar77.blp",
"LoadScreenUlduar80.blp",
"LOADSCREENULDUARRAID.BLP",
"LoadScreenUldumDungeon.blp",
"LOADSCREENUTGARDE.BLP",
"LoadScreenUtgardePinnecle.blp",
"LoadScreenWailingCaverns.blp",
"LoadScreenWintergrasp.blp",
"LOADSCREENZULAMAN.BLP",
"LoadScreenZulFarrak.blp",
"LoadScreenZulGurub.blp"
}