local T, C, L, _ = unpack(select(2, ...))

local _, ns = ...
local oUF = ns.oUF or oUF

local cfg = C.Module.Unitframe
local DUF = T.Unitframe

local UNIT_CLASS = T.class
local mediaPath = cfg.mediaPath

local media = {
    portrait_overlay            = mediaPath .. "uf_portrait_overlay",
    foreground                  = mediaPath .. C.Media.style .. "\\" .. "uf_player_foreground",
    foreground_hightthreat      = mediaPath .. C.Media.style .. "\\" .. "uf_player_foreground_highthreat",
    foreground_lowthreat        = mediaPath .. C.Media.style .. "\\" .. "uf_player_foreground_lowthreat",
    background                  = mediaPath .. C.Media.style .. "\\" .. "uf_player_background",
    debuffHighlight             = mediaPath .. "uf_main_debuffHighlight",

    hpTex                       = mediaPath .. "uf_bartex_main_hp",
    mpTex                       = mediaPath .. "uf_bartex_main_power",
    druidManaTex                = mediaPath .. "uf_bartex_druidmana",

    castbar_barTex              = mediaPath .. "uf_bartex_normal",
    castbar_foreground          = mediaPath .. C.Media.style .. "\\" .. "uf_castbar_foreground",
    castbar_background          = mediaPath .. C.Media.style .. "\\" .. "uf_castbar_background",

    expbar_barTex               = mediaPath .. "uf_bartex_normal",
    repbar_barTex               = mediaPath .. "uf_bartex_normal",

    Incoming_barTex             = mediaPath .. "uf_bartex_normal",
}

local createTexture = function(self)
    -- foreground
    self.FrameFG = CreateFrame("Frame", nil, self)
    self.FrameFG:SetFrameStrata("LOW")
    self.FrameFG:SetFrameLevel(5)

    self.FrameFG.texture = self.FrameFG:CreateTexture(nil, "BORDER")
    self.FrameFG.texture:SetTexture(media.foreground)
    self.FrameFG.texture:SetAllPoints(self.FrameFG)

    self.FrameFG:SetSize(512, 128)
    self.FrameFG:SetPoint("CENTER", self, 60, 0)  

    -- background
    self.FrameBG = CreateFrame("Frame", nil, self)
    self.FrameBG:SetFrameStrata("BACKGROUND")
    self.FrameBG:SetFrameLevel(1)

    self.FrameBG.texture = self.FrameBG:CreateTexture(nil, "BACKGROUND")
    self.FrameBG.texture:SetTexture(media.background)
    self.FrameBG.texture:SetAllPoints(self.FrameBG)

    self.FrameBG:SetPoint("CENTER", self, 60, 0)
    self.FrameBG:SetSize(512, 128)

    --debuff highlight
    self.DebuffHighlight = self:CreateTexture(nil, "OVERLAY")
    self.DebuffHighlight:SetTexture(media.debuffHighlight)
    self.DebuffHighlight:SetVertexColor(0, 0, 0, 0)
    self.DebuffHighlight:SetBlendMode("ADD")
    self.DebuffHighlightAlpha = 0.9
    self.DebuffHighlightFilter = false

    self.DebuffHighlight:SetPoint("TOPLEFT", self.FrameFG, "TOPLEFT", -5, 5)   
    self.DebuffHighlight:SetPoint("BOTTOMRIGHT", self.FrameFG, "BOTTOMRIGHT", 5, -5)
end

local createBar = function(self)
    --health bar
    self.Health = CreateFrame("StatusBar", nil, self)
    self.Health:SetFrameStrata("LOW")
    self.Health:SetFrameLevel(3)
    self.Health:SetSize(261, 12)
    self.Health:SetPoint('CENTER', self, 73, 1)

    self.Health:SetStatusBarTexture(media.hpTex)
    self.Health:SetStatusBarColor(0.2, 0.2, 0.2)

    self.Health.frequentUpdates = true
    self.Health.colorSmooth = true
    self.Health.colorClass = cfg.player.colorHealth
    self.Health.Smooth = true

    --power bar
    self.Power = CreateFrame("StatusBar", nil, self)
    self.Power:SetPoint("CENTER")
    self.Power:SetFrameStrata("LOW")
    self.Power:SetFrameLevel(3) 
    self.Power:SetPoint('CENTER', self, 124, 3)
    self.Power:SetSize(160, 40)
    
    self.Power:SetStatusBarTexture(media.mpTex)

    self.Power.frequentUpdates = true
    self.Power.colorPower = true
    self.Power.Smooth = true

    self.Power.bg = self.Power:CreateTexture(nil, "BORDER")
    self.Power.bg.multiplier = .45
    self.Power.bg:SetAllPoints(self.Power)
    self.Power.bg:SetTexture(media.mpTex)

    --Incoming heal
    local mhpb = self.Health:CreateTexture(nil, "ARTWORK")
    mhpb:SetTexture(media.Incoming_barTex)
    mhpb:SetVertexColor(0, 1, 0.5, 0.2)

    local ohpb = self.Health:CreateTexture(nil, "ARTWORK")
    ohpb:SetTexture(media.Incoming_barTex)
    ohpb:SetVertexColor(0, 1, 0, 0.2)

    local ahpb = self.Health:CreateTexture(nil, "ARTWORK")
    ahpb:SetTexture(media.Incoming_barTex)
    ahpb:SetVertexColor(1, 1, 0, 0.2)

    self.HealPrediction = {
        myBar = mhpb,
        otherBar = ohpb,
        absorbBar = ahpb,
        maxOverflow = 1,
        frequentUpdates = true
    }
end

local createPortrait = function(self)
    local overlayFrame

    if cfg.portrait3D == false then
        self.Portrait = self.FrameBG:CreateTexture(nil, 'BACKGROUND', nil, 3)
        self.Portrait:SetSize(64, 64)
        
        overlayFrame = CreateFrame('Frame', nil, self.FrameBG)
    else
        self.Portrait = CreateFrame('PlayerModel', nil, self.FrameBG)
        self.Portrait:SetFrameLevel(3)
        self.Portrait:SetSize(50, 50)
        
        overlayFrame = CreateFrame('Frame', nil, self.Portrait)
    end
    
    self.Portrait:SetPoint("CENTER", self, -100, 6)

    overlayFrame:SetFrameLevel(4)
    overlayFrame:SetAllPoints(self.Portrait)
    
    local overlay = overlayFrame:CreateTexture(nil, 'BACKGROUND', nil, -7)
    overlay:SetTexture(media.portrait_overlay)
    overlay:SetPoint("TOPLEFT", overlayFrame, -10, 10)
    overlay:SetPoint("BOTTOMRIGHT", overlayFrame, 10, -10)
    overlay:SetAlpha(1)

    self.Portrait.overlay = overlay
end

local createTag = function(self)
    self.Tags = {}
    
    self.Tags.name = self:CreateTag(self.FrameFG, "[raidcolor][dd:realname]")
    :SetFont(STANDARD_TEXT_FONT, 14, "THICKOUTLINE")
    :SetPoint("LEFT", self.Health, -2, 20)
    :SetJustifyH('LEFT')
    :done()

    self.Tags.level = self:CreateTag(self.FrameFG, "[dd:difficulty][level]")
    :SetFont(STANDARD_TEXT_FONT, 14, "OUTLINE")
    :SetPoint("LEFT", self.Health, -92, -24)
    :SetJustifyH('RIGHT')
    :done()

    self.Tags.hp = self:CreateTag(self.FrameFG, "[dd:smarthp]")
    :SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
    :SetPoint("RIGHT", self.Health, -6, 0)
    :SetJustifyH('RIGHT')
    :done()

    self.Tags.pp = self:CreateTag(self.FrameFG, "[dd:pp]")
    :SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
    :SetPoint("LEFT", self.Health, 104, -14)
    :SetJustifyH('LEFT')
    :done()
end

local createCastbar = function(self)
    local castbar = CreateFrame("StatusBar", nil, self)
    castbar:SetStatusBarTexture(media.castbar_barTex)
    castbar:SetStatusBarColor(27/255, 147/255, 226/255)
    castbar:SetFrameStrata("LOW")
	castbar:SetFrameLevel(3)
    castbar:SetSize(246, 10)
    castbar:SetPoint(unpack(cfg.player.castbar.position))

    local fg = CreateFrame("Frame", nil, castbar)
    fg:SetPoint("CENTER", 38, 0)
    fg:SetSize(422, 94)

    fg.Texture = fg:CreateTexture(nil, "ARTWORK")
    fg.Texture:SetTexture(media.castbar_foreground)
    fg.Texture:SetAllPoints(fg)

    local bg = CreateFrame("Frame", nil, castbar)
    bg:SetFrameStrata("BACKGROUND")
    bg:SetPoint("CENTER", fg)
    bg:SetSize(422, 100)

    bg.Texture = bg:CreateTexture(nil, "ARTWORK")
    bg.Texture:SetTexture(media.castbar_background)
    bg.Texture:SetAllPoints(bg)

    castbar.Foreground = fg
    castbar.Background = bg

    local icon = castbar:CreateTexture(nil, "ARTWORK")
    icon:SetSize(20, 14)
    icon:SetPoint("LEFT", castbar, "RIGHT", -272, 0)
    icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
    castbar.Icon = icon

    local safe = castbar:CreateTexture(nil, "BORDER")
    safe:SetTexture(media.castbar_barTex)
    safe:SetVertexColor(231/255, 48/255, 78/255)
    safe:SetPoint("TOPRIGHT")
    safe:SetPoint("BOTTOMRIGHT")
    castbar.SafeZone = safe

    local spark = castbar:CreateTexture(nil,"LOW", nil, -7)
    spark:SetBlendMode("ADD")
    spark:SetVertexColor(0.8, 0.6, 0,1)
    spark:SetSize(15, castbar:GetHeight() * 2)
    castbar.Spark = spark

    local flash = CreateFrame("Frame", nil, Castbar)
    flash:SetAllPoints(castbar)
    castbar.Flash = flash

    local shield = castbar:CreateTexture(nil, 'BACKGROUND')
    shield:SetTexture(0,0,0,0)
    castbar.Shield = shield

    local text = DUF.CreateFont(castbar, STANDARD_TEXT_FONT, 12, "OUTLINE")
    text:SetPoint("BOTTOMLEFT", castbar, "TOPLEFT", 0, 10)
    text:SetJustifyH('LEFT')
    castbar.Text = text

    local time = DUF.CreateFont(castbar, STANDARD_TEXT_FONT, 12, "OUTLINE")
    time:SetPoint("RIGHT", castbar, "RIGHT", -4, 0)
    time:SetJustifyH("RIGHT")
    castbar.Time = time

    castbar.PostCastStart = DUF.PostCastStart
    castbar.PostCastFailed = DUF.PostCastFailed
    castbar.PostCastInterrupted = DUF.PostCastInterrupted
    castbar.PostCastInterruptible = DUF.UpdateCastbarColor
    castbar.PostCastNotInterruptible = DUF.UpdateCastbarColor
    castbar.PostCastStop = DUF.PostStop
    castbar.PostChannelStop = DUF.PostStop
    castbar.PostChannelStart = DUF.PostChannelStart

    if cfg.player.castbar.enableFader then
        self.CCastbar = castbar
    else
        self.Castbar = castbar
    end
end

local createThreadType = function(self)
    local event_handler = function(self, event, unit)
        if(unit and unit ~= self.unit) then
            return
        end

        local file = media.foreground
        local status = UnitCanAttack(self.unit, "target") and UnitThreatSituation(self.unit, "target") or UnitThreatSituation(self.unit)

        if status == 3 then
            file = media.foreground_hightthreat
        elseif status ~= nil then
            file = media.foreground_lowthreat
        end

        self.FrameFG.texture:SetTexture(file)
    end

    self:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE", event_handler)
    self:RegisterEvent("PLAYER_TARGET_CHANGED", event_handler)
    table.insert(self.__elements, event_handler)
end

local createClassModule = function(self)
    DUF.classModule.UpdateComboPointsPosition(self, cfg, media)

    -- Totems
    if cfg.classModule[UNIT_CLASS].showTotems then
        DUF.classModule.UpdateTotems(self, cfg, media)
    end
    -- Alternate Mana Bar
    if cfg.classModule[UNIT_CLASS].showAdditionalPower then
        DUF.classModule.CreateAlternatePowerBar(self, cfg, media)
    end
    -- Load Class Modules
    if DUF.classModule[UNIT_CLASS] then
        self.classPowerBar = DUF.classModule[UNIT_CLASS](self, cfg, media)
    end
end

local createStyle = function(self)
    self.colors = C.oUF_colors
    self.cUnit = "player"
        
    self:SetPoint(unpack(cfg.player.position))
    self:SetSize(270, 45)
    self:SetScale(cfg.scale)
    
    self:RegisterForClicks("AnyUp")
    self:SetScript("OnEnter", UnitFrame_OnEnter)
    self:SetScript("OnLeave", UnitFrame_OnLeave)

    createTexture(self)
    createBar(self)
    createPortrait(self)
    createTag(self)
    createCastbar(self)
    createThreadType(self)
    createClassModule(self)

    self.Resting = DUF.CreateIcon(self, "BACKGROUND", 28, -1, self, "RIGHT", "LEFT", 14, 36)
    self.Resting:SetTexCoord(0, 0.5, 0, 0.421875)

    self.PvP = DUF.CreateIcon(self, "BACKGROUND", 38, -1, self, "TOP", "BOTTOMLEFT", -14, 45)
    self.PvPTimer = self:CreateTag(self, "[dd:pvptimer]", .5)
    :SetFont(STANDARD_TEXT_FONT, 12, "OUTLINE")
    :SetPoint("TOP", self.PvP, 'BOTTOM', -22, 24)
    :SetJustifyH('CENTER')
    :done()

    self.Combat = DUF.CreateIcon(self, "BACKGROUND", 28, -1, self, "LEFT", "RIGHT", 82, 0)
    self.Combat:SetTexCoord(0, 0.5, 0, 0.421875)

    self.Leader = DUF.CreateIcon(self.FrameBG, "BACKGROUND", 24, -1, self, "BOTTOMLEFT", "TOPLEFT", 82, 5)

    self.Assistant = DUF.CreateIcon(self.FrameBG, "BACKGROUND", 24, -1, self, "BOTTOMLEFT", "TOPLEFT", 78, 7)

    self.MasterLooter = DUF.CreateIcon(self.FrameBG, "BACKGROUND", 24, -1, self, "TOPLEFT", "BOTTOMLEFT", 12, 0)

    self.RaidIcon = DUF.CreateIcon(self, "BACKGROUND", 24, -1, self, "CENTER", "CENTER", 40, 0)
    self.RaidIcon:SetTexCoord(0, 0.5, 0, 0.421875)

    self.LFDRole = DUF.CreateIcon(self, "BACKGROUND", 22, -1, self, "TOPLEFT", "TOPLEFT", 52, -26)
	self.LFDRole:SetTexCoord(0, 0.5, 0, 0.421875)

    DUF.SetFader(self, cfg.player.fader)
end

---------------------------------------------
-- SPAWN PLAYER UNIT
---------------------------------------------
oUF:RegisterStyle("superUI:player", createStyle)
oUF:SetActiveStyle("superUI:player")
oUF:Spawn("player", "superUIPlayerFrame")
