-- Rack & Ruin: Roulette.lua
-- American wheel (0 and 00). Session chip count, resets whenever the table
-- is opened. Bets and chip totals are tracked locally per client (honor
-- system - no privacy or cheating concerns here, unlike Poker's hidden
-- hands). Only the spin result itself needs to be agreed on, so the host
-- generates the number and broadcasts it; everyone resolves their own bet
-- against it independently.

RackAndRuin = RackAndRuin or {}

local ORANGE = { 1, 0.55, 0.1 }
local GAME_ID = "ROULETTE"
local STARTING_CHIPS = 500

local RED_NUMBERS = {
    [1]=true,[3]=true,[5]=true,[7]=true,[9]=true,[12]=true,[14]=true,[16]=true,
    [18]=true,[19]=true,[21]=true,[23]=true,[25]=true,[27]=true,[30]=true,
    [32]=true,[34]=true,[36]=true,
}

local function NumberColor(n)
    if n == "0" or n == "00" then return "green" end
    local num = tonumber(n)
    if RED_NUMBERS[num] then return "red" end
    return "black"
end

local frame = CreateFrame("Frame", "RackAndRuinRouletteFrame", UIParent, "BackdropTemplate")
frame:SetSize(700, 560)
frame:SetPoint("CENTER")
frame:SetMovable(true)
frame:EnableMouse(true)
frame:RegisterForDrag("LeftButton")
frame:SetScript("OnDragStart", frame.StartMoving)
frame:SetScript("OnDragStop", frame.StopMovingOrSizing)
frame:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Buttons\\WHITE8x8",
    edgeSize = 2,
})
frame:SetBackdropColor(0, 0, 0, 0.97)
frame:SetBackdropBorderColor(unpack(ORANGE))
frame:SetFrameStrata("HIGH")
frame:SetToplevel(true)
frame:Hide()

local statusText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
statusText:SetPoint("TOP", 0, -28)
statusText:SetTextColor(1, 0.85, 0.2)
statusText:SetText("")

local chipsText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
chipsText:SetPoint("TOPLEFT", 36, -28)
chipsText:SetTextColor(1, 1, 1)

local resultText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge")
resultText:SetPoint("TOP", 0, -80)
resultText:SetText("")

local tableText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
tableText:SetPoint("TOPLEFT", 36, -60)
tableText:SetWidth(90)
tableText:SetJustifyH("LEFT")
tableText:SetJustifyV("TOP")
tableText:SetTextColor(0.7, 0.7, 0.7)
tableText:SetText("")

-- ============================================================
-- Bet type selection (radio-style buttons)
-- ============================================================
local BET_TYPES = {
    { id = "RED",     label = "Red",       payout = 1 },
    { id = "BLACK",   label = "Black",     payout = 1 },
    { id = "EVEN",    label = "Even",      payout = 1 },
    { id = "ODD",     label = "Odd",       payout = 1 },
    { id = "LOW",     label = "1-18",      payout = 1 },
    { id = "HIGH",    label = "19-36",     payout = 1 },
    { id = "DOZEN1",  label = "1st 12",    payout = 2 },
    { id = "DOZEN2",  label = "2nd 12",    payout = 2 },
    { id = "DOZEN3",  label = "3rd 12",    payout = 2 },
}

local function StyledButton(parent, text, width, height)
    local btn = CreateFrame("Button", nil, parent, "BackdropTemplate")
    btn:SetSize(width or 150, height or 36)
    btn:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8x8",
        edgeFile = "Interface\\Buttons\\WHITE8x8",
        edgeSize = 2,
    })
    btn:SetBackdropColor(0, 0, 0, 1)
    btn:SetBackdropBorderColor(unpack(ORANGE))

    local label = btn:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    label:SetPoint("CENTER")
    label:SetText(text)
    label:SetTextColor(1, 0.85, 0.6)
    btn.label = label

    btn:SetScript("OnEnter", function(self) if not self.selected then self:SetBackdropColor(0.2, 0.1, 0, 1) end end)
    btn:SetScript("OnLeave", function(self) if not self.selected then self:SetBackdropColor(0, 0, 0, 1) end end)

    return btn
end

local betButtons = {}
local selectedBetType = nil
local selectedNumber = nil -- straight-up bet, e.g. "17", "0", "00"

local function ClearBetSelectionVisuals()
    for _, btn in pairs(betButtons) do
        btn.selected = false
        btn:SetBackdropColor(unpack(btn.defaultColor))
    end
end

for i, bet in ipairs(BET_TYPES) do
    local col = (i - 1) % 3
    local row = math.floor((i - 1) / 3)
    local btn = StyledButton(frame, bet.label, 150, 36)
    btn:SetPoint("TOPLEFT", 36 + col * 160, -230 - row * 44)

    if bet.id == "BLACK" then
        btn.defaultColor = { 0, 0, 0, 1 }
        -- leave default black-background styling as-is
    elseif bet.id == "RED" then
        btn.defaultColor = { 0.6, 0.05, 0.05, 1 }
        btn:SetBackdropColor(unpack(btn.defaultColor))
        btn:SetBackdropBorderColor(unpack(ORANGE))
        btn.label:SetTextColor(0, 0, 0)
        btn:SetScript("OnEnter", function(self) if not self.selected then self:SetBackdropColor(0.75, 0.1, 0.1, 1) end end)
        btn:SetScript("OnLeave", function(self) if not self.selected then self:SetBackdropColor(unpack(self.defaultColor)) end end)
    else
        btn.defaultColor = { 0.9, 0.9, 0.9, 1 }
        btn:SetBackdropColor(unpack(btn.defaultColor))
        btn:SetBackdropBorderColor(unpack(ORANGE))
        btn.label:SetTextColor(0, 0, 0)
        btn:SetScript("OnEnter", function(self) if not self.selected then self:SetBackdropColor(1, 1, 1, 1) end end)
        btn:SetScript("OnLeave", function(self) if not self.selected then self:SetBackdropColor(unpack(self.defaultColor)) end end)
    end

    btn:SetScript("OnClick", function()
        ClearBetSelectionVisuals()
        selectedBetType = bet.id
        selectedNumber = nil
        btn.selected = true
        btn:SetBackdropColor(0.35, 0.15, 0, 1)
    end)
    betButtons[bet.id] = btn
end

-- Straight-up number bet via edit box (0-36, or "00")
local numberLabel = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
numberLabel:SetPoint("TOPLEFT", 36, -370)
numberLabel:SetText("Straight number bet (0-36 or 00):")
numberLabel:SetTextColor(0.8, 0.8, 0.8)

local numberBox = CreateFrame("EditBox", nil, frame, "InputBoxTemplate")
numberBox:SetSize(60, 24)
numberBox:SetPoint("LEFT", numberLabel, "RIGHT", 12, 0)
numberBox:SetAutoFocus(false)
numberBox:SetMaxLetters(2)
numberBox:SetScript("OnEnterPressed", function(self)
    local val = self:GetText()
    if val == "00" or (tonumber(val) and tonumber(val) >= 0 and tonumber(val) <= 36) then
        ClearBetSelectionVisuals()
        selectedNumber = val
        selectedBetType = nil
        self:SetTextColor(1, 0.85, 0.2)
    else
        self:SetTextColor(1, 0.3, 0.3)
    end
    self:ClearFocus()
end)

-- Wager amount
local wager = 10
local wagerText = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
wagerText:SetPoint("TOPLEFT", 36, -410)
wagerText:SetTextColor(1, 1, 1)

local function UpdateWagerText()
    wagerText:SetText("Wager: " .. wager .. " chips")
end
UpdateWagerText()

local function WagerButton(text, delta)
    local btn = StyledButton(frame, text, 60, 30)
    btn:SetScript("OnClick", function()
        wager = math.max(10, wager + delta)
        UpdateWagerText()
    end)
    return btn
end

local wagerMinus = WagerButton("-10", -10)
wagerMinus:SetPoint("LEFT", wagerText, "RIGHT", 16, 0)
local wagerPlus = WagerButton("+10", 10)
wagerPlus:SetPoint("LEFT", wagerMinus, "RIGHT", 8, 0)

-- ============================================================
-- Buttons: Spin / Back to Menu
-- ============================================================
local spinButton = StyledButton(frame, "Spin", 170, 42)
spinButton:SetPoint("BOTTOM", frame, "BOTTOM", -95, 30)

local backButton = StyledButton(frame, "Back to Menu", 170, 42)
backButton:SetPoint("LEFT", spinButton, "RIGHT", 16, 0)
backButton:SetScript("OnClick", function()
    frame:Hide()
    RackAndRuin.ShowMenu()
end)

-- ============================================================
-- Chip tracking (local, per-client, resets on ShowRoulette)
-- ============================================================
local myChips = STARTING_CHIPS
local myName = UnitName("player")

local function UpdateChipsText()
    chipsText:SetText(myName .. ": " .. myChips .. " chips")
end

local function ResolveBet(resultNumber)
    local color = NumberColor(resultNumber)
    local numVal = tonumber(resultNumber)
    local won = false
    local payout = 0

    if selectedNumber then
        if selectedNumber == resultNumber then
            won = true
            payout = wager * 35
        end
    elseif selectedBetType then
        if selectedBetType == "RED" and color == "red" then won, payout = true, wager * 1
        elseif selectedBetType == "BLACK" and color == "black" then won, payout = true, wager * 1
        elseif numVal then
            if selectedBetType == "EVEN" and numVal ~= 0 and numVal % 2 == 0 then won, payout = true, wager * 1
            elseif selectedBetType == "ODD" and numVal % 2 == 1 then won, payout = true, wager * 1
            elseif selectedBetType == "LOW" and numVal >= 1 and numVal <= 18 then won, payout = true, wager * 1
            elseif selectedBetType == "HIGH" and numVal >= 19 and numVal <= 36 then won, payout = true, wager * 1
            elseif selectedBetType == "DOZEN1" and numVal >= 1 and numVal <= 12 then won, payout = true, wager * 2
            elseif selectedBetType == "DOZEN2" and numVal >= 13 and numVal <= 24 then won, payout = true, wager * 2
            elseif selectedBetType == "DOZEN3" and numVal >= 25 and numVal <= 36 then won, payout = true, wager * 2
            end
        end
    end

    if not selectedNumber and not selectedBetType then
        statusText:SetText("No bet placed - chips unchanged.")
        return
    end

    if won then
        myChips = myChips + payout
        statusText:SetText("You win " .. payout .. " chips!")
    else
        myChips = myChips - wager
        statusText:SetText("No win this spin.")
    end
    UpdateChipsText()
end

local function ShowSpinResult(resultNumber)
    local color = NumberColor(resultNumber)
    local colorRGB = { r = 1, g = 1, b = 1 }
    if color == "red" then colorRGB = { r = 1, g = 0.3, b = 0.3 }
    elseif color == "black" then colorRGB = { r = 0.8, g = 0.8, b = 0.8 }
    elseif color == "green" then colorRGB = { r = 0.3, g = 1, b = 0.3 } end

    resultText:SetText(resultNumber)
    resultText:SetTextColor(colorRGB.r, colorRGB.g, colorRGB.b)

    ResolveBet(resultNumber)
end

-- ============================================================
-- Host spin + network wiring
-- ============================================================
local function HostSpin()
    local roll = math.random(0, 37) -- 0-36 plus one extra slot for "00"
    local resultNumber
    if roll == 37 then
        resultNumber = "00"
    else
        resultNumber = tostring(roll)
    end
    RackAndRuin.Net.Send(GAME_ID, "RESULT", resultNumber)
    ShowSpinResult(resultNumber)
end

RackAndRuin.Net.RegisterHandler(GAME_ID, "RESULT", function(sender, payload)
    if not RackAndRuin.Net.IsHost() then
        ShowSpinResult(payload)
    end
end)

spinButton:SetScript("OnClick", function()
    if not selectedNumber and not selectedBetType then
        statusText:SetText("Pick a bet before spinning.")
        return
    end
    if wager > myChips then
        statusText:SetText("Not enough chips for that wager.")
        return
    end

    if RackAndRuin.Net.IsHost() then
        HostSpin()
    else
        RackAndRuin.Net.Send(GAME_ID, "REQUESTSPIN", "")
    end
end)

-- Non-host players can ask the host to spin (e.g. everyone's bet is placed)
RackAndRuin.Net.RegisterHandler(GAME_ID, "REQUESTSPIN", function(sender, payload)
    if RackAndRuin.Net.IsHost() then
        HostSpin()
    end
end)

-- ============================================================
-- Show/reset
-- ============================================================
function RackAndRuin.ShowRoulette()
    frame:Show()
    myChips = STARTING_CHIPS
    wager = 10
    selectedBetType = nil
    selectedNumber = nil
    ClearBetSelectionVisuals()
    numberBox:SetText("")
    UpdateChipsText()
    UpdateWagerText()
    resultText:SetText("")
    statusText:SetText("Place your bet, then Spin.")

    local others = {}
    for _, name in ipairs(RackAndRuin.Net.GetPlayers()) do
        if name ~= myName then table.insert(others, name) end
    end
    if #others > 0 then
        tableText:SetText("At the table:\n" .. table.concat(others, "\n"))
    else
        tableText:SetText("")
    end

    if RackAndRuin.Net.IsGrouped() and not RackAndRuin.Net.IsHost() then
        spinButton.label:SetText("Ready to Spin")
    else
        spinButton.label:SetText("Spin")
    end
end

RackAndRuin.RouletteFrame = frame
