Imports System.Collections.Generic
Imports System.Drawing
Imports System.Windows.Forms

Public Class Form1
    Inherits Form

    ' Game variables
    Private deck As New List(Of Card)
    Private players As New List(Of Player)
    Private currentPlayerIndex As Integer = 0
    Private gameStarted As Boolean = False
    Private WithEvents turnTimer As New Timer()

    ' UI containers
    Private mainPanel As Panel
    Private playerPanels As New List(Of Panel)
    Private handPanels As New List(Of FlowLayoutPanel)
    Private scoreLabels As New List(Of Label)
    Private messageLabel As Label
    Private statusLabel As Label
    Private startButton As Button
    Private askButton As Button
    Private drawButton As Button
    Private cardButtons As New List(Of Button)

    ' Card class
    Private Class Card
        Public Property Suit As String
        Public Property Rank As String
        Public Property Value As Integer

        Public Overrides Function ToString() As String
            Return $"{Rank} of {Suit}"
        End Function

        Public Function GetImageName() As String
            Return $"{Rank}_of_{Suit}".ToLower()
        End Function
    End Class

    ' Player class
    Private Class Player
        Public Property Name As String
        Public Property Hand As New List(Of Card)
        Public Property Sets As New List(Of List(Of Card))
        Public Property Score As Integer = 0
        Public Property IsAI As Boolean = False

        Public Sub New(name As String, Optional isAI As Boolean = False)
            Me.Name = name
            Me.IsAI = isAI
        End Sub
    End Class

    Public Sub New()
        InitializeForm()
        InitializeGame()
    End Sub

    Private Sub InitializeForm()
        Me.Text = "Bonken - Dutch Card Game"
        Me.Size = New Size(1200, 800)
        Me.StartPosition = FormStartPosition.CenterScreen
        Me.BackColor = Color.DarkGreen

        ' Main panel
        mainPanel = New Panel()
        mainPanel.Dock = DockStyle.Fill
        mainPanel.BackColor = Color.DarkGreen
        Me.Controls.Add(mainPanel)

        ' Status label
        statusLabel = New Label()
        statusLabel.Text = "Welcome to Bonken! Click Start Game to begin."
        statusLabel.Font = New Font("Arial", 14, FontStyle.Bold)
        statusLabel.ForeColor = Color.White
        statusLabel.Size = New Size(800, 30)
        statusLabel.Location = New Point(200, 20)
        statusLabel.TextAlign = ContentAlignment.MiddleCenter
        mainPanel.Controls.Add(statusLabel)

        ' Message label
        messageLabel = New Label()
        messageLabel.Text = ""
        messageLabel.Font = New Font("Arial", 12)
        messageLabel.ForeColor = Color.Yellow
        messageLabel.Size = New Size(800, 30)
        messageLabel.Location = New Point(200, 60)
        messageLabel.TextAlign = ContentAlignment.MiddleCenter
        mainPanel.Controls.Add(messageLabel)

        ' Start button
        startButton = New Button()
        startButton.Text = "Start New Game"
        startButton.Font = New Font("Arial", 12)
        startButton.Size = New Size(150, 40)
        startButton.Location = New Point(50, 20)
        startButton.BackColor = Color.LightBlue
        AddHandler startButton.Click, AddressOf StartGame_Click
        mainPanel.Controls.Add(startButton)

        ' Ask button
        askButton = New Button()
        askButton.Text = "Ask for Card"
        askButton.Font = New Font("Arial", 12)
        askButton.Size = New Size(150, 40)
        askButton.Location = New Point(50, 70)
        askButton.BackColor = Color.LightGreen
        askButton.Enabled = False
        AddHandler askButton.Click, AddressOf AskButton_Click
        mainPanel.Controls.Add(askButton)

        ' Draw button
        drawButton = New Button()
        drawButton.Text = "Draw from Deck"
        drawButton.Font = New Font("Arial", 12)
        drawButton.Size = New Size(150, 40)
        drawButton.Location = New Point(50, 120)
        drawButton.BackColor = Color.LightCoral
        drawButton.Enabled = False
        AddHandler drawButton.Click, AddressOf DrawButton_Click
        mainPanel.Controls.Add(drawButton)

        ' Turn timer
        turnTimer.Interval = 2000
        AddHandler turnTimer.Tick, AddressOf AITurn

        ' Create player panels
        CreatePlayerPanels()
    End Sub

    Private Sub CreatePlayerPanels()
        ' Clear existing panels
        For Each panel In playerPanels
            mainPanel.Controls.Remove(panel)
        Next
        playerPanels.Clear()
        handPanels.Clear()
        scoreLabels.Clear()

        ' Player positions
        Dim positions As New List(Of Point) From {
            New Point(250, 500),   ' Bottom (Human)
            New Point(800, 300),   ' Right (AI 1)
            New Point(250, 100),   ' Top (AI 2)
            New Point(50, 300)     ' Left (AI 3)
        }

        For i As Integer = 0 To 3
            ' Player panel
            Dim panel As New Panel()
            panel.Size = New Size(300, 180)
            panel.Location = positions(i)
            panel.BackColor = Color.FromArgb(100, 255, 255, 255)
            panel.BorderStyle = BorderStyle.FixedSingle

            ' Player name label
            Dim nameLabel As New Label()
            nameLabel.Text = If(i = 0, "You", $"AI Player {i}")
            nameLabel.Font = New Font("Arial", 12, FontStyle.Bold)
            nameLabel.ForeColor = Color.Black
            nameLabel.Location = New Point(10, 10)
            nameLabel.Size = New Size(150, 25)
            panel.Controls.Add(nameLabel)

            ' Score label
            Dim scoreLabel As New Label()
            scoreLabel.Text = "Score: 0"
            scoreLabel.Font = New Font("Arial", 10)
            scoreLabel.ForeColor = Color.DarkBlue
            scoreLabel.Location = New Point(10, 40)
            scoreLabel.Size = New Size(150, 20)
            panel.Controls.Add(scoreLabel)
            scoreLabels.Add(scoreLabel)

            ' Hand panel (for cards)
            Dim handPanel As New FlowLayoutPanel()
            handPanel.Size = New Size(280, 100)
            handPanel.Location = New Point(10, 70)
            handPanel.BackColor = Color.Transparent
            handPanel.AutoScroll = True
            panel.Controls.Add(handPanel)
            handPanels.Add(handPanel)

            ' Sets label
            Dim setsLabel As New Label()
            setsLabel.Text = "Sets: 0"
            setsLabel.Font = New Font("Arial", 10)
            setsLabel.ForeColor = Color.DarkGreen
            setsLabel.Location = New Point(170, 40)
            setsLabel.Size = New Size(100, 20)
            setsLabel.Name = "setsLabel"
            panel.Controls.Add(setsLabel)

            ' Current player indicator
            Dim indicator As New Label()
            indicator.Text = "▶"
            indicator.Font = New Font("Arial", 16, FontStyle.Bold)
            indicator.ForeColor = Color.Red
            indicator.Location = New Point(270, 10)
            indicator.Size = New Size(20, 20)
            indicator.Visible = False
            indicator.Name = $"indicator_{i}"
            panel.Controls.Add(indicator)

            playerPanels.Add(panel)
            mainPanel.Controls.Add(panel)
        Next
    End Sub

    Private Sub InitializeGame()
        ' Create deck
        Dim suits As String() = {"Hearts", "Diamonds", "Clubs", "Spades"}
        Dim ranks As String() = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"}

        deck.Clear()
        For Each suit In suits
            For Each rank In ranks
                Dim card As New Card()
                card.Suit = suit
                card.Rank = rank
                card.Value = Array.IndexOf(ranks, rank) + 1
                deck.Add(card)
            Next
        Next

        ' Create players
        players.Clear()
        players.Add(New Player("You", False)) ' Human player
        For i As Integer = 1 To 3
            players.Add(New Player($"AI Player {i}", True))
        Next
    End Sub

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

        While n > 1
            n -= 1
            Dim k As Integer = rnd.Next(n + 1)
            Dim value As Card = deck(k)
            deck(k) = deck(n)
            deck(n) = value
        End While
    End Sub

    Private Sub DealCards()
        ' Deal 5 cards to each player
        For Each player In players
            player.Hand.Clear()
            For i As Integer = 1 To 5
                If deck.Count > 0 Then
                    player.Hand.Add(deck(0))
                    deck.RemoveAt(0)
                End If
            Next
        Next

        ' Check for initial sets
        For Each player In players
            CheckForSets(player)
        Next
    End Sub

    Private Sub StartGame_Click(sender As Object, e As EventArgs)
        InitializeGame()
        ShuffleDeck()
        DealCards()

        gameStarted = True
        currentPlayerIndex = 0

        startButton.Enabled = False
        askButton.Enabled = True
        drawButton.Enabled = True

        UpdateUI()
        UpdateStatus("Game started! Your turn. Select a card to ask for.")
    End Sub

    Private Sub UpdateUI()
        ' Clear all card buttons
        For Each btn In cardButtons
            mainPanel.Controls.Remove(btn)
        Next
        cardButtons.Clear()

        ' Update player panels
        For i As Integer = 0 To players.Count - 1
            Dim player As Player = players(i)
            Dim handPanel As FlowLayoutPanel = handPanels(i)
            Dim scoreLabel As Label = scoreLabels(i)

            ' Clear hand panel
            handPanel.Controls.Clear()

            ' Update score
            scoreLabel.Text = $"Score: {player.Score}"

            ' Update sets count
            Dim setsLabel As Label = CType(playerPanels(i).Controls.Find("setsLabel", True)(0), Label)
            setsLabel.Text = $"Sets: {player.Sets.Count}"

            ' Update current player indicator
            Dim indicator As Label = CType(playerPanels(i).Controls.Find($"indicator_{i}", True)(0), Label)
            indicator.Visible = (i = currentPlayerIndex)

            ' Display cards (only show human player's cards)
            If i = 0 Then ' Human player
                For Each card In player.Hand
                    Dim cardBtn As New Button()
                    cardBtn.Text = $"{card.Rank}{vbCrLf}{card.Suit.Substring(0, 1)}"
                    cardBtn.Font = New Font("Arial", 10)
                    cardBtn.Size = New Size(60, 80)

                    ' Color code the suits
                    Select Case card.Suit
                        Case "Hearts"
                            cardBtn.ForeColor = Color.Red
                            cardBtn.BackColor = Color.White
                        Case "Diamonds"
                            cardBtn.ForeColor = Color.Red
                            cardBtn.BackColor = Color.LightYellow
                        Case "Clubs"
                            cardBtn.ForeColor = Color.Black
                            cardBtn.BackColor = Color.White
                        Case "Spades"
                            cardBtn.ForeColor = Color.Black
                            cardBtn.BackColor = Color.LightGray
                    End Select

                    cardBtn.Tag = card
                    AddHandler cardBtn.Click, AddressOf CardButton_Click
                    handPanel.Controls.Add(cardBtn)
                    cardButtons.Add(cardBtn)
                Next
            Else ' AI players - show back of cards
                For Each card In player.Hand
                    Dim cardBack As New Label()
                    cardBack.Text = "🂠"
                    cardBack.Font = New Font("Arial", 20)
                    cardBack.Size = New Size(60, 80)
                    cardBack.TextAlign = ContentAlignment.MiddleCenter
                    cardBack.BackColor = Color.Blue
                    cardBack.ForeColor = Color.White
                    handPanel.Controls.Add(cardBack)
                Next
            End If
        Next

        ' Update deck count display
        Dim deckLabel As Label = If(mainPanel.Controls.ContainsKey("deckLabel"),
                                   CType(mainPanel.Controls("deckLabel"), Label),
                                   New Label())
        deckLabel.Name = "deckLabel"
        deckLabel.Text = $"Deck: {deck.Count} cards"
        deckLabel.Font = New Font("Arial", 12, FontStyle.Bold)
        deckLabel.ForeColor = Color.White
        deckLabel.Size = New Size(150, 30)
        deckLabel.Location = New Point(50, 180)
        deckLabel.TextAlign = ContentAlignment.MiddleCenter

        If Not mainPanel.Controls.ContainsKey("deckLabel") Then
            mainPanel.Controls.Add(deckLabel)
        End If

        ' Check for game end
        If deck.Count = 0 AndAlso AllHandsEmpty() Then
            EndGame()
        End If
    End Sub

    Private Sub CardButton_Click(sender As Object, e As EventArgs)
        If Not gameStarted OrElse currentPlayerIndex <> 0 Then
            Return
        End If

        Dim selectedCard As Card = CType(CType(sender, Button).Tag, Card)
        AskForCard(selectedCard)
    End Sub

    Private Sub AskButton_Click(sender As Object, e As EventArgs)
        If Not gameStarted OrElse currentPlayerIndex <> 0 Then
            Return
        End If

        ' If no card selected, show message
        If messageLabel.Text.Contains("Select a card") Then
            UpdateStatus("Please select a card from your hand first.")
        End If
    End Sub

    Private Sub DrawButton_Click(sender As Object, e As EventArgs)
        If Not gameStarted OrElse currentPlayerIndex <> 0 Then
            Return
        End If

        DrawFromDeck()
    End Sub

    Private Sub AskForCard(selectedCard As Card)
        Dim currentPlayer As Player = players(currentPlayerIndex)
        Dim askedRank As String = selectedCard.Rank

        ' Ask each other player for the card
        Dim gotCards As Boolean = False

        For i As Integer = 1 To players.Count - 1
            Dim targetIndex As Integer = (currentPlayerIndex + i) Mod players.Count
            Dim targetPlayer As Player = players(targetIndex)

            ' Find matching cards in target player's hand
            Dim matchingCards As List(Of Card) = targetPlayer.Hand.Where(Function(c) c.Rank = askedRank).ToList()

            If matchingCards.Count > 0 Then
                ' Transfer cards to current player
                For Each card In matchingCards
                    targetPlayer.Hand.Remove(card)
                    currentPlayer.Hand.Add(card)
                Next

                UpdateStatus($"{currentPlayer.Name} got {matchingCards.Count} {askedRank}(s) from {targetPlayer.Name}!")
                gotCards = True

                ' Check for sets
                CheckForSets(currentPlayer)

                ' If player got cards, they get another turn
                UpdateUI()
                Return
            End If
        Next

        If Not gotCards Then
            UpdateStatus($"{currentPlayer.Name} asked for {askedRank} but no one had it. Go fish!")
            NextPlayer()
        End If

        UpdateUI()
    End Sub

    Private Sub DrawFromDeck()
        Dim currentPlayer As Player = players(currentPlayerIndex)

        If deck.Count > 0 Then
            Dim drawnCard As Card = deck(0)
            deck.RemoveAt(0)
            currentPlayer.Hand.Add(drawnCard)

            UpdateStatus($"{currentPlayer.Name} drew a card from the deck.")

            ' Check for sets
            CheckForSets(currentPlayer)
        Else
            UpdateStatus("Deck is empty!")
        End If

        NextPlayer()
        UpdateUI()
    End Sub

    Private Sub CheckForSets(player As Player)
        ' Group cards by rank
        Dim groups = player.Hand.GroupBy(Function(c) c.Rank)

        For Each group In groups
            ' If we have 4 cards of the same rank
            If group.Count() >= 4 Then
                ' Create a set
                Dim setCards As List(Of Card) = group.Take(4).ToList()

                ' Remove from hand
                For Each card In setCards
                    player.Hand.Remove(card)
                Next

                ' Add to sets
                player.Sets.Add(setCards)
                player.Score += 1

                UpdateStatus($"{player.Name} collected a set of {group.Key}s!")
            End If
        Next
    End Sub

    Private Sub NextPlayer()
        currentPlayerIndex = (currentPlayerIndex + 1) Mod players.Count

        ' Skip players with empty hands
        Dim attempts As Integer = 0
        While players(currentPlayerIndex).Hand.Count = 0 AndAlso attempts < players.Count
            currentPlayerIndex = (currentPlayerIndex + 1) Mod players.Count
            attempts += 1
        End While

        If currentPlayerIndex = 0 Then
            UpdateStatus("Your turn. Select a card to ask for.")
            askButton.Enabled = True
            drawButton.Enabled = True
        Else
            UpdateStatus($"{players(currentPlayerIndex).Name}'s turn...")
            askButton.Enabled = False
            drawButton.Enabled = False

            ' Start AI turn timer
            turnTimer.Start()
        End If
    End Sub

    Private Sub AITurn(sender As Object, e As EventArgs)
        turnTimer.Stop()

        Dim aiPlayer As Player = players(currentPlayerIndex)

        ' AI logic: ask for a random card from hand
        If aiPlayer.Hand.Count > 0 Then
            Dim rnd As New Random()

            ' Select random card rank from AI hand
            Dim selectedCard As Card = aiPlayer.Hand(rnd.Next(aiPlayer.Hand.Count))
            Dim askedRank As String = selectedCard.Rank

            Dim gotCards As Boolean = False

            ' Ask all other players
            For i As Integer = 1 To players.Count - 1
                Dim targetIndex As Integer = (currentPlayerIndex + i) Mod players.Count
                Dim targetPlayer As Player = players(targetIndex)

                Dim matchingCards As List(Of Card) =
                    targetPlayer.Hand.Where(Function(c) c.Rank = askedRank).ToList()

                If matchingCards.Count > 0 Then

                    For Each card As Card In matchingCards
                        targetPlayer.Hand.Remove(card)
                        aiPlayer.Hand.Add(card)
                    Next

                    UpdateStatus($"{aiPlayer.Name} received {matchingCards.Count} {askedRank}(s) from {targetPlayer.Name}.")

                    CheckForSets(aiPlayer)
                    gotCards = True

                    UpdateUI()

                    ' AI gets another turn after a short pause
                    turnTimer.Start()
                    Return
                End If
            Next

            If Not gotCards Then

                ' Go Fish
                If deck.Count > 0 Then
                    Dim drawnCard As Card = deck(0)
                    deck.RemoveAt(0)
                    aiPlayer.Hand.Add(drawnCard)

                    UpdateStatus($"{aiPlayer.Name} goes fishing and draws a card.")

                    CheckForSets(aiPlayer)
                Else
                    UpdateStatus($"{aiPlayer.Name} wanted to fish, but the deck is empty.")
                End If

                NextPlayer()
                UpdateUI()
            End If
        Else
            NextPlayer()
            UpdateUI()
        End If
    End Sub

    Private Function AllHandsEmpty() As Boolean
        For Each player As Player In players
            If player.Hand.Count > 0 Then
                Return False
            End If
        Next

        Return True
    End Function

    Private Sub EndGame()

        gameStarted = False
        turnTimer.Stop()

        askButton.Enabled = False
        drawButton.Enabled = False
        startButton.Enabled = True

        Dim winner As Player = players.OrderByDescending(Function(p) p.Score).First()

        Dim results As String = "Game Over!" & vbCrLf & vbCrLf

        For Each player As Player In players
            results &= $"{player.Name}: {player.Score} sets" & vbCrLf
        Next

        results &= vbCrLf & $"Winner: {winner.Name}!"

        MessageBox.Show(results, "Game Over", MessageBoxButtons.OK, MessageBoxIcon.Information)

        UpdateStatus($"Game Over! Winner: {winner.Name}")
    End Sub

    Private Sub UpdateStatus(message As String)
        statusLabel.Text = message
        messageLabel.Text = message
    End Sub

End Class
