Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    Private WithEvents btnStart As Button
    Private WithEvents btnDeal As Button
    Private WithEvents btnPlay As Button
    Private WithEvents lblStatus As Label

    Private playerPanels(3) As Panel
    Private playerLabels(3) As Label
    Private playerCards(3) As List(Of PictureBox)

    Private deck As New List(Of String)
    Private playerHands(3) As List(Of String)
    Private currentPlayer As Integer = 0
    Private trickCards As New List(Of String)
    Private trickSuit As String = ""
    Private scores(3) As Integer

    Public Sub New()
        Me.Text = "Black Lady Card Game"
        Me.Size = New Size(1200, 900)
        Me.StartPosition = FormStartPosition.CenterScreen

        ''InitializeComponent()

        For i As Integer = 0 To 3
            playerCards(i) = New List(Of PictureBox)
            playerHands(i) = New List(Of String)
        Next

        InitializeControls()
        InitializeDeck()

    End Sub

    Private Sub InitializeControls()
        ' Status label
        lblStatus = New Label()
        lblStatus.Text = "Click Start to begin game"
        lblStatus.Location = New Point(20, 20)
        lblStatus.Size = New Size(300, 30)
        lblStatus.Font = New Font("Arial", 12, FontStyle.Bold)
        Me.Controls.Add(lblStatus)

        ' Start button
        btnStart = New Button()
        btnStart.Text = "Start Game"
        btnStart.Location = New Point(350, 20)
        btnStart.Size = New Size(100, 30)
        Me.Controls.Add(btnStart)

        ' Deal button
        btnDeal = New Button()
        btnDeal.Text = "Deal Cards"
        btnDeal.Location = New Point(460, 20)
        btnDeal.Size = New Size(100, 30)
        btnDeal.Enabled = False
        Me.Controls.Add(btnDeal)

        ' Play button
        btnPlay = New Button()
        btnPlay.Text = "Play Card"
        btnPlay.Location = New Point(570, 20)
        btnPlay.Size = New Size(100, 30)
        btnPlay.Enabled = False
        Me.Controls.Add(btnPlay)

        ' Create player panels
        Dim panelLocations() As Point = {
            New Point(50, 100),   ' Player 1 (Bottom)
            New Point(50, 275),   ' Player 2 (Left)
            New Point(50, 450),  ' Player 3 (Right)
            New Point(50, 625)    ' Player 4 (Top)
        }

        Dim panelSizes() As Size = {
            New Size(800, 150),   ' Bottom player
            New Size(800, 150),   ' Left player
            New Size(800, 150),   ' Right player
            New Size(800, 150)    ' Top player
        }

        For i As Integer = 0 To 3
            playerPanels(i) = New Panel()
            playerPanels(i).Location = panelLocations(i)
            playerPanels(i).Size = panelSizes(i)
            playerPanels(i).BorderStyle = BorderStyle.FixedSingle
            playerPanels(i).BackColor = Color.LightGreen

            playerLabels(i) = New Label()
            playerLabels(i).Text = "Player " & (i + 1)
            playerLabels(i).Location = New Point(10, 10)
            playerLabels(i).Font = New Font("Arial", 10, FontStyle.Bold)
            playerPanels(i).Controls.Add(playerLabels(i))

            Me.Controls.Add(playerPanels(i))
        Next

        ' Center area for played cards
        Dim centerPanel As New Panel()
        centerPanel.Location = New Point(900, 325)
        centerPanel.Size = New Size(200, 200)
        centerPanel.BackColor = Color.LightYellow
        centerPanel.BorderStyle = BorderStyle.FixedSingle
        centerPanel.Tag = "CenterCard"
        Me.Controls.Add(centerPanel)
    End Sub

    Private Sub InitializeDeck()
        Dim suits() As String = {"H", "D", "C", "S"}
        Dim ranks() As String = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}

        For Each suit As String In suits
            For Each rank As String In ranks
                deck.Add(rank & suit)
            Next
        Next
    End Sub

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        lblStatus.Text = "Game started! Click Deal to distribute cards"
        btnStart.Enabled = False
        btnDeal.Enabled = True

        ' Reset game state
        For i As Integer = 0 To 3
            playerHands(i).Clear()
            scores(i) = 0
        Next
        deck.Clear()
        InitializeDeck()
    End Sub

    Private Sub btnDeal_Click(sender As Object, e As EventArgs) Handles btnDeal.Click
        lblStatus.Text = "Dealing cards..."
        btnDeal.Enabled = False

        ' Shuffle deck
        ShuffleDeck()

        ' Deal 13 cards to each player
        Dim cardIndex As Integer = 0
        For i As Integer = 0 To 51
            playerHands(cardIndex Mod 4).Add(deck(i))
            cardIndex += 1
        Next

        ' Sort hands
        For i As Integer = 0 To 3
            playerHands(i).Sort(AddressOf CardComparer)
        Next

        ' Display cards for current player (Player 1)
        DisplayPlayerCards(0)

        lblStatus.Text = "Cards dealt! Player 1's turn"
        btnPlay.Enabled = True
        currentPlayer = 0
    End Sub

    Private Sub ShuffleDeck()
        Dim rnd As New Random()
        Dim n As Integer = deck.Count

        For i As Integer = n - 1 To 1 Step -1
            Dim j As Integer = rnd.Next(0, i + 1)
            Dim temp As String = deck(i)
            deck(i) = deck(j)
            deck(j) = temp
        Next
    End Sub

    Private Function CardComparer(card1 As String, card2 As String) As Integer
        Dim suitOrder As New Dictionary(Of String, Integer) From {
            {"C", 0}, {"D", 1}, {"S", 2}, {"H", 3}
        }

        Dim rankOrder As New Dictionary(Of String, Integer) From {
            {"2", 2}, {"3", 3}, {"4", 4}, {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8},
            {"9", 9}, {"10", 10}, {"J", 11}, {"Q", 12}, {"K", 13}, {"A", 14}
        }

        Dim suit1 As String = card1.Substring(card1.Length - 1)
        Dim suit2 As String = card2.Substring(card2.Length - 1)

        Dim rank1 As String = card1.Substring(0, card1.Length - 1)
        Dim rank2 As String = card2.Substring(0, card2.Length - 1)

        If suitOrder(suit1) <> suitOrder(suit2) Then
            Return suitOrder(suit1).CompareTo(suitOrder(suit2))
        Else
            Return rankOrder(rank1).CompareTo(rankOrder(rank2))
        End If
    End Function

    Private Sub DisplayPlayerCards(playerIndex As Integer)
        ' Clear existing card displays
        For Each panel As Panel In playerPanels
            For i As Integer = panel.Controls.Count - 1 To 0 Step -1
                If TypeOf panel.Controls(i) Is PictureBox Then
                    panel.Controls(i).Dispose()
                End If
            Next
        Next

        playerCards(playerIndex).Clear()

        ' Display cards for the specified player
        Dim hand As List(Of String) = playerHands(playerIndex)
        Dim xPos As Integer = 50
        Dim yPos As Integer = 50

        For i As Integer = 0 To hand.Count - 1
            Dim cardPic As New PictureBox()
            cardPic.Size = New Size(60, 90)
            cardPic.Location = New Point(xPos, yPos)
            cardPic.BorderStyle = BorderStyle.FixedSingle
            cardPic.BackColor = Color.White
            cardPic.Tag = hand(i)
            cardPic.Cursor = Cursors.Hand

            Dim bmp As New Bitmap(60, 90)

            Using g As Graphics = Graphics.FromImage(bmp)

                g.Clear(Color.White)

                Dim cardText As String = GetCardDisplay(hand(i))
                Dim font As New Font("Arial", 10)

                Dim brush As Brush =
        If(hand(i).EndsWith("H") OrElse hand(i).EndsWith("D"),
           Brushes.Red,
           Brushes.Black)

                g.DrawString(cardText, font, brush, 5, 5)

                Dim suitSymbol As String =
        GetSuitSymbol(hand(i).Substring(hand(i).Length - 1))

                Dim suitFont As New Font("Arial", 20)

                g.DrawString(suitSymbol, suitFont, brush, 15, 30)

            End Using

            cardPic.Image = bmp

            AddHandler cardPic.Click, AddressOf Card_Click

            playerPanels(playerIndex).Controls.Add(cardPic)
            playerCards(playerIndex).Add(cardPic)

            xPos += 70
            If xPos > 700 Then
                xPos = 50
                yPos += 100
            End If
        Next
    End Sub

    Private Function GetCardDisplay(card As String) As String
        Dim rank As String = card.Substring(0, card.Length - 1)
        Return rank
    End Function

    Private Function GetSuitSymbol(suit As String) As String
        Select Case suit
            Case "H" : Return "♥"
            Case "D" : Return "♦"
            Case "C" : Return "♣"
            Case "S" : Return "♠"
            Case Else : Return ""
        End Select
    End Function

    Private Sub Card_Click(sender As Object, e As EventArgs)
        If btnPlay.Enabled Then
            Dim clickedCard As PictureBox = DirectCast(sender, PictureBox)
            Dim cardValue As String = clickedCard.Tag.ToString()

            ' Highlight selected card
            For Each cardPic As PictureBox In playerCards(currentPlayer)
                cardPic.BorderStyle = BorderStyle.FixedSingle
            Next
            clickedCard.BorderStyle = BorderStyle.Fixed3D

            ' Enable play button
            btnPlay.Tag = cardValue
        End If
    End Sub

    Private Sub btnPlay_Click(sender As Object, e As EventArgs) Handles btnPlay.Click
        If btnPlay.Tag Is Nothing Then
            MessageBox.Show("Please select a card to play!")
            Return
        End If

        Dim playedCard As String = btnPlay.Tag.ToString()

        ' Validate move (must follow suit if possible)
        If trickSuit <> "" AndAlso playerHands(currentPlayer).Any(Function(c) c.EndsWith(trickSuit)) Then
            If Not playedCard.EndsWith(trickSuit) Then
                MessageBox.Show("You must follow suit!")
                Return
            End If
        End If

        ' Remove card from player's hand
        playerHands(currentPlayer).Remove(playedCard)

        ' Add to trick
        trickCards.Add(playedCard)

        ' Set trick suit if first card
        If trickSuit = "" Then
            trickSuit = playedCard.Substring(playedCard.Length - 1)
        End If

        ' Display played card in center
        DisplayPlayedCard(playedCard, currentPlayer)

        ' Move to next player
        currentPlayer = (currentPlayer + 1) Mod 4

        If trickCards.Count = 4 Then
            ' Trick complete - determine winner
            DetermineTrickWinner()
            trickCards.Clear()
            trickSuit = ""

            ' Clear center area
            For Each ctrl As Control In Me.Controls
                If ctrl.Tag IsNot Nothing AndAlso ctrl.Tag.ToString().StartsWith("CenterCard") Then
                    ctrl.Controls.Clear()
                End If
            Next
        End If

        ' Update display for next player
        If playerHands(currentPlayer).Count > 0 Then
            DisplayPlayerCards(currentPlayer)
            lblStatus.Text = "Player " & (currentPlayer + 1) & "'s turn"
        Else
            ' End of round
            CalculateScores()
            lblStatus.Text = "Round ended! Click Start for new game"
            btnStart.Enabled = True
            btnPlay.Enabled = False
        End If

        btnPlay.Tag = Nothing
    End Sub

    Private Sub DisplayPlayedCard(card As String, playerIndex As Integer)
        Dim positions() As Point = {
            New Point(100, 50),   ' Player 1 (Bottom)
            New Point(10, 50),    ' Player 2 (Left)
            New Point(130, 50),   ' Player 3 (Right)
            New Point(100, 10)    ' Player 4 (Top)
        }

        Dim cardPic As New PictureBox()
        cardPic.Size = New Size(60, 90)
        cardPic.Location = positions(playerIndex)
        cardPic.BackColor = Color.White
        cardPic.BorderStyle = BorderStyle.FixedSingle
        cardPic.Tag = "CenterCard_" & playerIndex

        Dim bmp As New Bitmap(60, 90)

        Using g As Graphics = Graphics.FromImage(bmp)

            g.Clear(Color.White)

            Dim cardText As String = GetCardDisplay(card)
            Dim font As New Font("Arial", 10)

            Dim brush As Brush =
        If(card.EndsWith("H") OrElse card.EndsWith("D"),
           Brushes.Red,
           Brushes.Black)

            g.DrawString(cardText, font, brush, 5, 5)

            Dim suitSymbol As String =
        GetSuitSymbol(card.Substring(card.Length - 1))

            Dim suitFont As New Font("Arial", 20)

            g.DrawString(suitSymbol, suitFont, brush, 15, 30)

        End Using

        cardPic.Image = bmp

        ' Find center panel and add card
        For Each ctrl As Control In Me.Controls
            If ctrl.BackColor = Color.LightYellow Then
                ctrl.Controls.Add(cardPic)
                Exit For
            End If
        Next
    End Sub

    Private Sub DetermineTrickWinner()
        Dim winningIndex As Integer = 0
        Dim highestCard As String = trickCards(0)

        For i As Integer = 1 To 3
            If IsCardHigher(trickCards(i), highestCard, trickSuit) Then
                highestCard = trickCards(i)
                winningIndex = i
            End If
        Next

        ' Calculate points for this trick
        Dim trickPoints As Integer = 0
        For Each card As String In trickCards
            If card = "QH" Then ' Black Lady
                trickPoints += 13
            ElseIf card.EndsWith("H") Then ' Other hearts
                trickPoints += 1
            End If
        Next

        scores(winningIndex) += trickPoints

        MessageBox.Show("Player " & (winningIndex + 1) & " wins the trick! (" & trickPoints & " points)")
    End Sub

    Private Function IsCardHigher(card1 As String, card2 As String, leadSuit As String) As Boolean
        Dim rankOrder As New Dictionary(Of String, Integer) From {
            {"2", 2}, {"3", 3}, {"4", 4}, {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8},
            {"9", 9}, {"10", 10}, {"J", 11}, {"Q", 12}, {"K", 13}, {"A", 14}
        }

        Dim suit1 As String = card1.Substring(card1.Length - 1)
        Dim suit2 As String = card2.Substring(card2.Length - 1)

        Dim rank1 As String = card1.Substring(0, card1.Length - 1)
        Dim rank2 As String = card2.Substring(0, card2.Length - 1)

        ' Cards must follow suit
        If suit1 = leadSuit AndAlso suit2 <> leadSuit Then
            Return True
        ElseIf suit1 <> leadSuit AndAlso suit2 = leadSuit Then
            Return False
        ElseIf suit1 = leadSuit AndAlso suit2 = leadSuit Then
            Return rankOrder(rank1) > rankOrder(rank2)
        End If

        Return False
    End Function

    Private Sub CalculateScores()
        Dim scoreMessage As String = "Round Scores:" & vbCrLf
        For i As Integer = 0 To 3
            scoreMessage &= "Player " & (i + 1) & ": " & scores(i) & " points" & vbCrLf
        Next

        ' Check for shooting the moon (collecting all hearts + Q♠)
        For i As Integer = 0 To 3
            If scores(i) = 26 Then ' All 13 hearts + Black Lady
                scores(i) = 0
                For j As Integer = 0 To 3
                    If j <> i Then
                        scores(j) = 26
                    End If
                Next
                scoreMessage &= vbCrLf & "Player " & (i + 1) & " shot the moon!"
                Exit For
            End If
        Next

        MessageBox.Show(scoreMessage)
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        MyBase.OnPaint(e)

        ' Draw game title
        Using font As New Font("Arial", 16, FontStyle.Bold)
            e.Graphics.DrawString("BLACK LADY CARD GAME", font, Brushes.DarkBlue, New PointF(300, 60))
        End Using
    End Sub
End Class
