Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    ' Game constants
    Private Const CARD_WIDTH As Integer = 75
    Private Const CARD_HEIGHT As Integer = 105
    Private Const PLAYER_COUNT As Integer = 4
    Private Const MAX_ROUNDS As Integer = 13

    Private ReadOnly SUITS As String() = {"♥", "♦", "♣", "♠"}
    Private ReadOnly RANKS As String() = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
    Private ReadOnly CARD_VALUES As Integer() = {&HE, &H2, &H3, &H4, &H5, &H6, &H7, &H8, &H9, &HA, &HB, &HC, &HD}

    ' Game state
    Private deck As New List(Of Card)
    Private players As New List(Of Player)
    Private currentRound As Integer = &H1
    Private currentTrick As Integer = &H1
    Private currentPlayerIndex As Integer = &H0
    Private cardsInRound As Integer
    Private trumpSuit As Integer = -&H1
    Private trickCards As New List(Of Card)
    Private trickLeaderIndex As Integer = &H0
    Private bids As New Dictionary(Of Integer, Integer)
    Private tricksWon As New Dictionary(Of Integer, Integer)

    ' UI Controls
    Private WithEvents btnNewGame As Button
    Private WithEvents btnDeal As Button
    Private WithEvents btnStartBidding As Button
    Private WithEvents btnPlayCard As Button
    Private lblRound As Label
    Private lblTrump As Label
    Private lblStatus As Label
    Private flowPlayerPanels As New FlowLayoutPanel()
    Private playerPanels As New List(Of Panel)
    Private cardButtons As New List(Of Button)
    Private bidTextBoxes As New List(Of TextBox)
    Private trickPanel As New Panel()

    Public Sub New()
        InitializeComponent2()
        InitializeGame()
    End Sub

    Private Sub InitializeComponent2()
        ' Form setup
        Me.Text = "Oh Hell Card Game"
        Me.Size = New Size(&H3E8, &H320)
        Me.StartPosition = FormStartPosition.CenterScreen
        CenterToScreen()
        MaximizeBox = False
        FormBorderStyle = FormBorderStyle.FixedSingle
        Font = New Font("Consolas", 10)

        ' Control panel
        Dim controlPanel As New Panel With {
            .Dock = DockStyle.Top,
            .Height = &H32,
            .BackColor = Color.DarkGreen
        }

        ' Game controls
        btnNewGame = New Button With {
            .Text = "New Game",
            .Location = New Point(&HA, &HA),
            .ForeColor = Color.White,
            .Size = New Size(&H5A, &H1E)
        }

        btnDeal = New Button With {
            .Text = "Deal Cards",
            .Location = New Point(&H6E, &HA),
            .ForeColor = Color.White,
            .Size = New Size(&H6A, &H1E),
            .Enabled = False
        }

        btnStartBidding = New Button With {
            .Text = "Start Bidding",
            .Location = New Point(&HE2, &HA),
            .ForeColor = Color.White,
            .Size = New Size(&H7A, &H1E),
            .Enabled = False
        }

        btnPlayCard = New Button With {
            .Text = "Play Card",
            .Location = New Point(&H166, &HA),
            .ForeColor = Color.White,
            .Size = New Size(&H5A, &H1E),
            .Enabled = False
        }

        lblRound = New Label With {
            .Text = "Round: 1",
            .Location = New Point(&H1DA, &HA),
            .Size = New Size(&H5A, &H1E),
            .ForeColor = Color.White,
            .Font = New Font("Arial", &HA, FontStyle.Bold)
        }

        lblTrump = New Label With {
            .Text = "Trump: None",
            .Location = New Point(&H238, &HA),
            .Size = New Size(&H64, &H1E),
            .ForeColor = Color.White,
            .Font = New Font("Arial", &HA, FontStyle.Bold)
        }

        lblStatus = New Label With {
            .Text = "Welcome to Oh Hell!",
            .Dock = DockStyle.Bottom,
            .Height = &H1E,
            .BackColor = Color.Navy,
            .ForeColor = Color.Yellow,
            .Font = New Font("Arial", &HB, FontStyle.Bold),
            .TextAlign = ContentAlignment.MiddleCenter
        }

        ' Add controls to control panel
        controlPanel.Controls.AddRange({btnNewGame, btnDeal, btnStartBidding, btnPlayCard, lblRound, lblTrump})

        ' Player panels container
        flowPlayerPanels.Dock = DockStyle.Fill
        flowPlayerPanels.BackColor = Color.ForestGreen

        ' Trick panel
        trickPanel.Size = New Size(&H12C, &HA6)
        trickPanel.BackColor = Color.DarkGreen
        trickPanel.BorderStyle = BorderStyle.Fixed3D
        trickPanel.Location = New Point((Me.Width - trickPanel.Width) \ &H2, &H96 + 100)
        trickPanel.Visible = False

        ' Add to form
        Me.Controls.AddRange({controlPanel, flowPlayerPanels, lblStatus, trickPanel})
    End Sub

    Private Sub InitializeGame()
        ' Initialize players
        players.Clear()
        For i As Integer = &H0 To PLAYER_COUNT - &H1
            players.Add(New Player($"Player {i + &H1}", &H0))
        Next

        ' Initialize UI panels
        CreatePlayerPanels()
    End Sub

    Private Sub CreatePlayerPanels()
        flowPlayerPanels.Controls.Clear()
        playerPanels.Clear()
        bidTextBoxes.Clear()

        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim panel As New Panel With {
                .Size = New Size(&HC8, &HF0),
                .BorderStyle = BorderStyle.FixedSingle,
                .BackColor = Color.LightGreen
            }

            Dim lblName As New Label With {
                .Text = players(i).Name,
                .Location = New Point(&HA, &H3A),
                .Size = New Size(&H78, &H14),
                .Font = New Font("Arial", &H9, FontStyle.Bold)
            }

            Dim lblScore As New Label With {
                .Text = $"Score: {players(i).Score}",
                .Location = New Point(&HA, &H58),
                .Size = New Size(&H78, &H14),
                .Name = $"lblScore{i}"
            }

            Dim lblBid As New Label With {
                .Text = "Bid: 0",
                .Location = New Point(&HA, &H6C),
                .Size = New Size(&H78, &H14),
                .Name = $"lblBid{i}"
            }

            Dim lblTricks As New Label With {
                .Text = "Tricks: 0",
                .Location = New Point(&HA, &H80),
                .Size = New Size(&H78, &H14),
                .Name = $"lblTricks{i}"
            }

            Dim txtBid As New TextBox With {
                .Location = New Point(&HA, &H94),
                .Size = New Size(&H32, &H14),
                .Visible = False,
                .Name = $"txtBid{i}"
            }

            panel.Controls.AddRange({lblName, lblScore, lblBid, lblTricks, txtBid})
            flowPlayerPanels.Controls.Add(panel)
            playerPanels.Add(panel)
            bidTextBoxes.Add(txtBid)
        Next
    End Sub

    Private Sub UpdatePlayerDisplay()
        For i As Integer = &H0 To players.Count - &H1
            Dim scoreLabel = CType(playerPanels(i).Controls($"lblScore{i}"), Label)
            Dim bidLabel = CType(playerPanels(i).Controls($"lblBid{i}"), Label)
            Dim tricksLabel = CType(playerPanels(i).Controls($"lblTricks{i}"), Label)

            scoreLabel.Text = $"Score: {players(i).Score}"
            bidLabel.Text = $"Bid: {If(bids.ContainsKey(i), bids(i), &H0)}"
            tricksLabel.Text = $"Tricks: {If(tricksWon.ContainsKey(i), tricksWon(i), &H0)}"
        Next
    End Sub

    Private Sub CreateDeck()
        deck.Clear()
        For suit As Integer = &H0 To &H3
            For rank As Integer = &H0 To &HC
                deck.Add(New Card(rank, suit))
            Next
        Next
    End Sub

    Private Sub ShuffleDeck()
        Dim rng As New Random()
        Dim n As Integer = deck.Count
        While n > &H1
            n -= &H1
            Dim k As Integer = rng.Next(n + &H1)
            Dim value As Card = deck(k)
            deck(k) = deck(n)
            deck(n) = value
        End While
    End Sub

    Private Sub DealCards()
        ' Clear previous cards
        For Each btn In cardButtons
            btn.Dispose()
        Next
        cardButtons.Clear()

        ' Calculate cards per player
        cardsInRound = currentRound
        If cardsInRound * PLAYER_COUNT > deck.Count Then
            cardsInRound = deck.Count \ PLAYER_COUNT
        End If

        ' Deal cards to players
        For i As Integer = &H0 To PLAYER_COUNT - &H1
            players(i).Hand.Clear()
            For j As Integer = &H0 To cardsInRound - &H1
                players(i).Hand.Add(deck(&H0))
                deck.RemoveAt(&H0)
            Next
            players(i).Hand.Sort(Function(c1, c2) c1.GetSortValue().CompareTo(c2.GetSortValue()))
        Next

        ' Set trump card
        If deck.Count > &H0 Then
            trumpSuit = deck(&H0).Suit
            lblTrump.Text = $"Trump: {SUITS(trumpSuit)}"
        End If

        ' Display player cards
        DisplayPlayerCards(&H0)
    End Sub

    Private Sub DisplayPlayerCards(playerIndex As Integer)
        Dim panel = playerPanels(playerIndex)
        Dim yPos As Integer = &H78

        ' Remove existing card buttons for this player
        For Each ctrl In panel.Controls.OfType(Of Button).ToList()
            If ctrl.Name.StartsWith("card") Then
                panel.Controls.Remove(ctrl)
                ctrl.Dispose()
            End If
        Next

        ' Add new card buttons
        For i As Integer = &H0 To players(playerIndex).Hand.Count - &H1
            Dim card = players(playerIndex).Hand(i)
            Dim btn As New Button With {
                .Text = $"{RANKS(card.Rank)}{SUITS(card.Suit)}",
                .Location = New Point(&HA + (i Mod &H3) * &H32, yPos + (i \ &H3) * &H1E + 60),
                .Size = New Size(&H2D, &H1E),
                .Tag = card,
                .Name = $"card{playerIndex}_{i}",
                .BackColor = If(card.Suit < &H2, Color.LightCoral, Color.LightGray)
            }
            AddHandler btn.Click, AddressOf CardButton_Click
            panel.Controls.Add(btn)
            cardButtons.Add(btn)
        Next
    End Sub

    Private Sub StartBiddingPhase()
        lblStatus.Text = "Bidding Phase - Enter your bids"

        ' Show bid textboxes for all players
        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim txtBid = bidTextBoxes(i)
            txtBid.Visible = True
            txtBid.Text = ""
            txtBid.Focus()
        Next

        btnPlayCard.Enabled = False
        btnStartBidding.Enabled = True
    End Sub

    Private Sub StartBiddingPhase2()
        lblStatus.Text = "Bidding Phase - Enter your bids"
        For Each txtBid In bidTextBoxes
            txtBid.Visible = True
            txtBid.Text = ""
        Next
        btnPlayCard.Enabled = False
    End Sub

    Private Sub StartPlayingPhase()
        lblStatus.Text = $"Playing Phase - {players(currentPlayerIndex).Name}'s turn to lead"

        ' Highlight whose turn it is
        HighlightCurrentPlayer()

        ' Clear trick panel
        trickCards.Clear()
        trickPanel.Controls.Clear()
        trickPanel.Visible = True
        trickPanel.BringToFront()

        ' Enable only current player's cards
        For Each btn In cardButtons
            btn.Enabled = btn.Name.StartsWith($"card{currentPlayerIndex}_")
            If btn.Enabled Then
                btn.BackColor = If(CType(btn.Tag, Card).Suit < &H2, Color.LightCoral, Color.LightGray)
            Else
                btn.BackColor = SystemColors.Control
            End If
        Next

        btnPlayCard.Enabled = True
        btnStartBidding.Enabled = False
    End Sub

    Private Sub StartPlayingPhase2()
        lblStatus.Text = $"Playing Phase - {players(currentPlayerIndex).Name}'s turn"
        trickCards.Clear()
        trickPanel.Controls.Clear()
        trickPanel.Visible = True
        btnPlayCard.Enabled = True

        ' Enable only current player's cards
        For Each btn In cardButtons
            btn.Enabled = btn.Name.StartsWith($"card{currentPlayerIndex}_")
        Next
    End Sub

    Private Sub CardButton_Click(sender As Object, e As EventArgs)
        Dim btn = CType(sender, Button)
        Dim card = CType(btn.Tag, Card)

        ' Disable the played card
        btn.Enabled = False
        btn.BackColor = Color.LightBlue

        ' Add card to trick
        trickCards.Add(card)
        players(currentPlayerIndex).Hand.Remove(card)

        ' Display card in trick panel with player indicator
        Dim lblCard As New Label With {
            .Text = $"{players(currentPlayerIndex).Name}: {btn.Text}",
            .Size = New Size(&H64, &H1E),
            .BackColor = btn.BackColor,
            .TextAlign = ContentAlignment.MiddleCenter,
            .Font = New Font("Arial", &H8, FontStyle.Bold),
            .Location = New Point(&HA, &HA + (trickCards.Count - &H1) * &H23)
        }
        trickPanel.Controls.Add(lblCard)

        ' Move to next player
        Dim previousPlayer = currentPlayerIndex
        currentPlayerIndex = (currentPlayerIndex + &H1) Mod PLAYER_COUNT

        If trickCards.Count < PLAYER_COUNT Then
            ' Still waiting for more players to play
            lblStatus.Text = $"Playing Phase - {players(currentPlayerIndex).Name}'s turn"

            ' Update card display for next player
            DisplayPlayerCards(currentPlayerIndex)

            ' Highlight whose turn it is
            HighlightCurrentPlayer()
        Else
            ' Trick complete - determine winner
            DetermineTrickWinner()
        End If
    End Sub

    Private Sub HighlightCurrentPlayer()
        ' Highlight the current player's panel
        For i As Integer = &H0 To playerPanels.Count - &H1
            If i = currentPlayerIndex Then
                playerPanels(i).BackColor = Color.Gold
                playerPanels(i).BorderStyle = BorderStyle.Fixed3D
            Else
                playerPanels(i).BackColor = Color.LightGreen
                playerPanels(i).BorderStyle = BorderStyle.FixedSingle
            End If
        Next
    End Sub

    Private Sub CardButton2_Click(sender As Object, e As EventArgs)
        Dim btn = CType(sender, Button)
        btn.Enabled = False
        btn.BackColor = Color.LightBlue

        ' Add card to trick
        Dim card = CType(btn.Tag, Card)
        trickCards.Add(card)
        players(currentPlayerIndex).Hand.Remove(card)

        ' Display card in trick panel
        Dim lblCard As New Label With {
            .Text = btn.Text,
            .Size = New Size(&H2D, &H1E),
            .BackColor = btn.BackColor,
            .TextAlign = ContentAlignment.MiddleCenter,
            .Location = New Point(&HA + trickCards.Count * &H3C, &H32)
        }
        trickPanel.Controls.Add(lblCard)

        ' Move to next player
        currentPlayerIndex = (currentPlayerIndex + &H1) Mod PLAYER_COUNT

        If trickCards.Count = PLAYER_COUNT Then
            ' Trick complete
            DetermineTrickWinner()
        Else
            lblStatus.Text = $"Playing Phase - {players(currentPlayerIndex).Name}'s turn"
            DisplayPlayerCards(currentPlayerIndex)
        End If
    End Sub

    Private Sub DetermineTrickWinner()
        Dim winningCard As Card = trickCards(&H0)
        Dim winningIndex As Integer = &H0
        Dim leadSuit As Integer = winningCard.Suit

        For i As Integer = &H1 To trickCards.Count - &H1
            Dim card = trickCards(i)
            If card.Suit = winningCard.Suit Then
                If CARD_VALUES(card.Rank) > CARD_VALUES(winningCard.Rank) Then
                    winningCard = card
                    winningIndex = i
                End If
            ElseIf card.Suit = trumpSuit AndAlso winningCard.Suit <> trumpSuit Then
                winningCard = card
                winningIndex = i
            End If
        Next

        Dim actualWinnerIndex = (trickLeaderIndex + winningIndex) Mod PLAYER_COUNT
        tricksWon(actualWinnerIndex) = tricksWon(actualWinnerIndex) + &H1

        ' Highlight the winner
        For i As Integer = &H0 To playerPanels.Count - &H1
            If i = actualWinnerIndex Then
                playerPanels(i).BackColor = Color.Gold
            Else
                playerPanels(i).BackColor = Color.LightGreen
            End If
        Next

        lblStatus.Text = $"{players(actualWinnerIndex).Name} wins the trick with {winningCard}!"

        ''lblStatus.Text = $"{players(actualWinnerIndex).Name} wins the trick!"

        ' Update display
        UpdatePlayerDisplay()

        ' Reset for next trick
        currentTrick += &H1
        trickLeaderIndex = actualWinnerIndex
        currentPlayerIndex = trickLeaderIndex
        trickCards.Clear()

        If currentTrick > cardsInRound Then
            EndRound()
        Else
            trickPanel.Controls.Clear()
            StartPlayingPhase()
        End If
    End Sub

    Private Sub EndRound()
        ' Calculate scores
        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim bid = bids(i)
            Dim tricks = tricksWon(i)
            If bid = tricks Then
                players(i).Score += &HA + tricks
            Else
                players(i).Score -= Math.Abs(bid - tricks)
            End If
        Next

        UpdatePlayerDisplay()

        ' Check if game over
        If currentRound >= MAX_ROUNDS Then
            lblStatus.Text = "Game Over! Final Scores: " &
                            String.Join(", ", players.Select(Function(p) $"{p.Name}: {p.Score}"))
            btnDeal.Enabled = False
            btnStartBidding.Enabled = False
            btnPlayCard.Enabled = False
        Else
            currentRound += &H1
            currentTrick = &H1
            lblRound.Text = $"Round: {currentRound}"
            lblStatus.Text = $"Round {currentRound} complete! Click 'Deal Cards' for next round."
            btnDeal.Enabled = True
            btnStartBidding.Enabled = False
            btnPlayCard.Enabled = False
        End If
    End Sub

    ' Event Handlers
    Private Sub btnNewGame_Click(sender As Object, e As EventArgs) Handles btnNewGame.Click
        InitializeGame()
        currentRound = &H1
        lblRound.Text = "Round: 1"
        lblTrump.Text = "Trump: None"
        lblStatus.Text = "New game started. Click 'Deal Cards' to begin."
        btnDeal.Enabled = True
        btnStartBidding.Enabled = False
        btnPlayCard.Enabled = False
        trickPanel.Visible = False
    End Sub

    Private Sub btnDeal_Click(sender As Object, e As EventArgs) Handles btnDeal.Click
        CreateDeck()
        ShuffleDeck()
        DealCards()
        lblStatus.Text = $"Cards dealt! {cardsInRound} cards each."
        btnDeal.Enabled = False
        btnStartBidding.Enabled = True

        ' Start bidding phase
        StartBiddingPhase()
    End Sub

    Private Sub btnDeal2_Click(sender As Object, e As EventArgs) Handles btnDeal.Click
        CreateDeck()
        ShuffleDeck()
        DealCards()
        lblStatus.Text = $"Cards dealt! {cardsInRound} cards each."
        btnDeal.Enabled = False
        btnStartBidding.Enabled = True
    End Sub

    Private Sub btnStartBidding_Click(sender As Object, e As EventArgs) Handles btnStartBidding.Click
        ' Validate and collect bids
        Dim totalBids As Integer = &H0

        ' First pass: validate all bids
        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim txtBid = bidTextBoxes(i)
            If String.IsNullOrWhiteSpace(txtBid.Text) Then
                MessageBox.Show($"{players(i).Name} must enter a bid!", "Bid Required")
                txtBid.Focus()
                Return
            End If

            If Integer.TryParse(txtBid.Text, Nothing) Then
                Dim bidValue As Integer = Integer.Parse(txtBid.Text)
                If bidValue < &H0 OrElse bidValue > cardsInRound Then
                    MessageBox.Show($"Bid must be between 0 and {cardsInRound}", "Invalid Bid")
                    txtBid.Focus()
                    txtBid.SelectAll()
                    Return
                End If
            Else
                MessageBox.Show("Please enter a valid number for bid", "Invalid Bid")
                txtBid.Focus()
                txtBid.SelectAll()
                Return
            End If
        Next

        ' Second pass: collect bids and check total
        bids.Clear()
        tricksWon.Clear()

        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim bidValue As Integer = Integer.Parse(bidTextBoxes(i).Text)
            bids(i) = bidValue
            tricksWon(i) = &H0
            totalBids += bidValue
            bidTextBoxes(i).Visible = False
        Next

        ' Check if total bids equal cards in round (not allowed in some variants)
        If totalBids = cardsInRound Then
            Dim result = MessageBox.Show($"Total bids ({totalBids}) equals cards in round ({cardsInRound})." &
                                         vbCrLf & "This is not allowed in standard rules." &
                                         vbCrLf & "Do you want to continue anyway?",
                                         "Warning",
                                         MessageBoxButtons.YesNo,
                                         MessageBoxIcon.Warning)

            If result = DialogResult.No Then
                ' Reset bidding
                For Each txtBid In bidTextBoxes
                    txtBid.Visible = True
                    txtBid.Focus()
                Next
                Return
            End If
        End If

        ' Update display and start playing
        UpdatePlayerDisplay()
        lblStatus.Text = $"Bidding complete! Starting trick {currentTrick} of {cardsInRound}"

        ' Determine who starts (usually player to dealer's left, but we'll use player 0)
        trickLeaderIndex = &H0
        currentPlayerIndex = trickLeaderIndex

        ' Start playing phase
        StartPlayingPhase()
    End Sub

    Private Sub btnStartBidding2_Click(sender As Object, e As EventArgs) Handles btnStartBidding.Click
        ' Collect bids
        bids.Clear()
        tricksWon.Clear()

        For i As Integer = &H0 To PLAYER_COUNT - &H1
            Dim txtBid = bidTextBoxes(i)
            If Integer.TryParse(txtBid.Text, Nothing) Then
                Dim bidValue As Integer = Integer.Parse(txtBid.Text)
                If bidValue >= &H0 AndAlso bidValue <= cardsInRound Then
                    bids(i) = bidValue
                    tricksWon(i) = &H0
                    txtBid.Visible = False
                Else
                    MessageBox.Show($"Bid must be between 0 and {cardsInRound}", "Invalid Bid")
                    Return
                End If
            Else
                MessageBox.Show("Please enter a valid number for bid", "Invalid Bid")
                Return
            End If
        Next

        UpdatePlayerDisplay()
        StartPlayingPhase()
    End Sub

    Private Sub btnPlayCard_Click(sender As Object, e As EventArgs) Handles btnPlayCard.Click
        ' This button is now handled by card clicks
    End Sub
End Class

' Supporting Classes
Public Class Card
    Public Property Rank As Integer
    Public Property Suit As Integer

    Public Sub New(rank As Integer, suit As Integer)
        Me.Rank = rank
        Me.Suit = suit
    End Sub

    Public Function GetSortValue() As Integer
        Return Suit * &HD + Rank
    End Function
End Class

Public Class Player
    Public Property Name As String
    Public Property Score As Integer
    Public Property Hand As List(Of Card)

    Public Sub New(name As String, score As Integer)
        Me.Name = name
        Me.Score = score
        Hand = New List(Of Card)()
    End Sub
End Class

' Entry Point
Module Program
    Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
    End Sub
End Module

