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

Public Class Form1
    Inherits Form

    ' Game constants
    Private Const CARD_WIDTH As Integer = 80
    Private Const CARD_HEIGHT As Integer = 120
    Private Const PLAYER_HAND_TOP As Integer = 400
    Private Const TABLE_CENTER_X As Integer = 400
    Private Const TABLE_CENTER_Y As Integer = 200

    ' Game variables
    Private deck As New List(Of Card)
    Private players(3) As Player
    Private currentPlayer As Integer = 0
    Private trick As New List(Of Card)
    Private trumpSuit As CardSuit = CardSuit.Clubs
    Private gameStarted As Boolean = False

    ' Controls created at runtime
    Private playerHandPanels(3) As Panel
    Private tablePanel As Panel
    Private statusLabel As Label
    Private startButton As Button
    Private trumpLabel As Label

    ' Card and game classes
    Private Enum CardSuit
        Clubs
        Spades
        Hearts
        Diamonds
    End Enum

    Private Enum CardRank
        Seven = 7
        Eight = 8
        Nine = 9
        Ten = 10
        Jack = 11
        Queen = 12
        King = 13
        Ace = 14
    End Enum

    Private Class Card
        Public Property Suit As CardSuit
        Public Property Rank As CardRank
        Public Property IsTrump As Boolean = False
        Public Property Owner As Integer = -1
        Public Property Control As Button = Nothing

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

    Private Class Player
        Public Property Hand As New List(Of Card)
        Public Property Score As Integer = 0
        Public Property IsHuman As Boolean = False
        Public Property Team As Integer ' 0 or 1 for partnerships
    End Class

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

    Private Sub InitializeForm()
        Me.Text = "Klaverjassen - Dutch Card Game"
        Me.Size = New Size(900, 700)
        Me.BackColor = Color.DarkGreen
        Me.StartPosition = FormStartPosition.CenterScreen
    End Sub

    Private Sub InitializeControls()
        ' Status label
        statusLabel = New Label()
        statusLabel.Text = "Welcome to Klaverjassen! Click Start Game"
        statusLabel.ForeColor = Color.White
        statusLabel.Font = New Font("Arial", 12, FontStyle.Bold)
        statusLabel.Size = New Size(400, 30)
        statusLabel.Location = New Point(250, 20)
        Me.Controls.Add(statusLabel)

        ' Trump label
        trumpLabel = New Label()
        trumpLabel.Text = "Trump: Not set"
        trumpLabel.ForeColor = Color.Gold
        trumpLabel.Font = New Font("Arial", 11, FontStyle.Bold)
        trumpLabel.Size = New Size(200, 25)
        trumpLabel.Location = New Point(350, 60)
        Me.Controls.Add(trumpLabel)

        ' Start button
        startButton = New Button()
        startButton.Text = "Start Game"
        startButton.Size = New Size(120, 40)
        startButton.Location = New Point(390, 100)
        startButton.Font = New Font("Arial", 10, FontStyle.Bold)
        AddHandler startButton.Click, AddressOf StartGame_Click
        Me.Controls.Add(startButton)

        ' Table panel for cards in play
        tablePanel = New Panel()
        tablePanel.Size = New Size(500, 300)
        tablePanel.Location = New Point(200, 150)
        tablePanel.BackColor = Color.ForestGreen
        tablePanel.BorderStyle = BorderStyle.FixedSingle
        Me.Controls.Add(tablePanel)

        ' Create player hand panels
        For i As Integer = 0 To 3
            playerHandPanels(i) = New Panel()
            playerHandPanels(i).Size = New Size(800, 150)
            playerHandPanels(i).BackColor = Color.Transparent
            playerHandPanels(i).BorderStyle = BorderStyle.None
            Me.Controls.Add(playerHandPanels(i))
        Next

        ' Position player panels (bottom, left, top, right)
        playerHandPanels(0).Location = New Point(50, PLAYER_HAND_TOP) ' Bottom (human)
        playerHandPanels(1).Location = New Point(50, 50) ' Left
        playerHandPanels(2).Location = New Point(50, 50) ' Top
        playerHandPanels(3).Location = New Point(700, 50) ' Right
    End Sub

    Private Sub InitializeGame()
        ' Initialize players
        For i As Integer = 0 To 3
            players(i) = New Player()
            players(i).Team = i Mod 2 ' 0 or 1 for partnerships
            players(i).IsHuman = (i = 0) ' Only player 0 is human
        Next

        ' Initialize deck
        InitializeDeck()
    End Sub

    Private Sub InitializeDeck()
        deck.Clear()

        For Each suit As CardSuit In [Enum].GetValues(GetType(CardSuit))
            For Each rank As CardRank In [Enum].GetValues(GetType(CardRank))
                ' Klaverjassen uses cards 7 through Ace
                If rank >= CardRank.Seven Then
                    Dim card As New Card()
                    card.Suit = suit
                    card.Rank = rank
                    deck.Add(card)
                End If
            Next
        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()
        ' Clear all hands
        For Each player As Player In players
            player.Hand.Clear()
        Next

        ' Shuffle and deal 8 cards to each player
        ShuffleDeck()

        For i As Integer = 0 To 31
            Dim card As Card = deck(i)
            card.Owner = i \ 8 ' Distribute to players
            players(card.Owner).Hand.Add(card)
        Next

        ' Sort each player's hand
        For Each player As Player In players
            player.Hand.Sort(Function(c1, c2)
                                 If c1.Suit = c2.Suit Then
                                     Return c2.Rank.CompareTo(c1.Rank)
                                 Else
                                     Return c1.Suit.CompareTo(c2.Suit)
                                 End If
                             End Function)
        Next

        ' Determine trump (in Klaverjassen, the last card determines trump)
        Dim trumpCard As Card = deck(31)
        trumpSuit = trumpCard.Suit
        trumpLabel.Text = $"Trump: {trumpSuit}"
        trumpLabel.ForeColor = GetSuitColor(trumpSuit)
    End Sub

    Private Sub DisplayPlayerHands()
        ' Clear all card controls
        For Each panel As Panel In playerHandPanels
            panel.Controls.Clear()
        Next

        ' Display human player's hand (player 0)
        For i As Integer = 0 To players(0).Hand.Count - 1
            Dim card As Card = players(0).Hand(i)
            Dim cardButton As New Button()

            cardButton.Text = GetCardSymbol(card)
            cardButton.Size = New Size(CARD_WIDTH, CARD_HEIGHT)
            cardButton.Location = New Point(i * (CARD_WIDTH + 5), 10)
            cardButton.Font = New Font("Arial", 14, FontStyle.Bold)
            cardButton.ForeColor = GetSuitColor(card.Suit)
            cardButton.BackColor = Color.White

            ' Mark trump cards
            If card.Suit = trumpSuit Then
                cardButton.BackColor = Color.LightYellow
                card.IsTrump = True
            End If

            cardButton.Tag = card
            AddHandler cardButton.Click, AddressOf Card_Click

            card.Control = cardButton
            playerHandPanels(0).Controls.Add(cardButton)
        Next

        ' Display AI players' hands (face down)
        For p As Integer = 1 To 3
            For i As Integer = 0 To players(p).Hand.Count - 1
                Dim cardBack As New Button()
                cardBack.Text = "?"
                cardBack.Size = New Size(CARD_WIDTH, CARD_HEIGHT)
                cardBack.Location = New Point(i * (CARD_WIDTH + 5), 10)
                cardBack.Font = New Font("Arial", 14, FontStyle.Bold)
                cardBack.BackColor = Color.DarkBlue
                cardBack.ForeColor = Color.White
                cardBack.Enabled = False
                playerHandPanels(p).Controls.Add(cardBack)
            Next
        Next
    End Sub

    Private Sub DisplayTable()
        tablePanel.Controls.Clear()

        For i As Integer = 0 To trick.Count - 1
            Dim card As Card = trick(i)
            Dim cardButton As New Button()

            cardButton.Text = GetCardSymbol(card)
            cardButton.Size = New Size(CARD_WIDTH, CARD_HEIGHT)
            cardButton.Font = New Font("Arial", 14, FontStyle.Bold)
            cardButton.ForeColor = GetSuitColor(card.Suit)
            cardButton.BackColor = Color.White
            cardButton.Enabled = False

            ' Position cards around the table
            Dim angle As Double = i * Math.PI / 2
            Dim radius As Integer = 100
            Dim x As Integer = TABLE_CENTER_X + radius * Math.Cos(angle) - CARD_WIDTH \ 2
            Dim y As Integer = TABLE_CENTER_Y + radius * Math.Sin(angle) - CARD_HEIGHT \ 2

            cardButton.Location = New Point(x - 200, y - 150) ' Adjust for panel offset
            tablePanel.Controls.Add(cardButton)
        Next
    End Sub

    Private Sub Card_Click(sender As Object, e As EventArgs)
        If Not gameStarted OrElse currentPlayer <> 0 Then Return

        Dim cardButton As Button = DirectCast(sender, Button)
        Dim card As Card = DirectCast(cardButton.Tag, Card)

        ' Check if card is valid to play
        If IsValidMove(card, 0) Then
            PlayCard(card, 0)
            cardButton.Enabled = False
            cardButton.BackColor = Color.LightGray

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

            ' If trick is complete, evaluate it
            If trick.Count = 4 Then
                EvaluateTrick()
                trick.Clear()
                DisplayTable()
                currentPlayer = DetermineNextPlayer()
            End If

            ' AI players' turns
            If currentPlayer <> 0 Then
                PlayAITurn()
            End If

            UpdateStatus()
        Else
            MessageBox.Show("Invalid move! You must follow suit if possible.", "Invalid Move", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        End If
    End Sub

    Private Sub PlayCard(card As Card, playerIndex As Integer)
        ' Remove card from player's hand
        players(playerIndex).Hand.Remove(card)

        ' Add to trick
        trick.Add(card)
        card.Owner = playerIndex

        ' Update display
        DisplayTable()
        DisplayPlayerHands()
    End Sub

    Private Function IsValidMove(card As Card, playerIndex As Integer) As Boolean
        ' First card of trick can be anything
        If trick.Count = 0 Then Return True

        Dim leadingSuit As CardSuit = trick(0).Suit

        ' If player has cards of the leading suit, must play one
        Dim hasLeadingSuit As Boolean = players(playerIndex).Hand.Exists(Function(c) c.Suit = leadingSuit)

        If hasLeadingSuit Then
            Return card.Suit = leadingSuit
        End If

        ' If no leading suit, can play anything
        Return True
    End Function

    Private Sub PlayAITurn()
        ' Simple AI: play first valid card
        For Each card As Card In players(currentPlayer).Hand
            If IsValidMove(card, currentPlayer) Then
                PlayCard(card, currentPlayer)
                Exit For
            End If
        Next

        currentPlayer = (currentPlayer + 1) Mod 4

        ' Check if trick is complete
        If trick.Count = 4 Then
            EvaluateTrick()
            trick.Clear()
            DisplayTable()
            currentPlayer = DetermineNextPlayer()

            ' Continue with AI if it's still not human's turn
            If currentPlayer <> 0 Then
                PlayAITurn()
            End If
        End If
    End Sub

    Private Sub EvaluateTrick()
        If trick.Count <> 4 Then Return

        ' Determine winning card based on Klaverjassen rules
        Dim winningCard As Card = trick(0)
        Dim leadingSuit As CardSuit = winningCard.Suit

        For i As Integer = 1 To 3
            Dim card As Card = trick(i)

            ' Trump beats non-trump
            If card.Suit = trumpSuit AndAlso winningCard.Suit <> trumpSuit Then
                winningCard = card
            ElseIf card.Suit = trumpSuit AndAlso winningCard.Suit = trumpSuit Then
                ' Higher trump wins
                If GetCardValue(card) > GetCardValue(winningCard) Then
                    winningCard = card
                End If
            ElseIf card.Suit = leadingSuit AndAlso winningCard.Suit = leadingSuit Then
                ' Higher card of leading suit wins
                If GetCardValue(card) > GetCardValue(winningCard) Then
                    winningCard = card
                End If
            End If
        Next

        ' Award points to winning team
        Dim winningTeam As Integer = players(winningCard.Owner).Team
        Dim trickPoints As Integer = CalculateTrickPoints()

        players(winningTeam * 2).Score += trickPoints
        players(winningTeam * 2 + 1).Score += trickPoints

        statusLabel.Text = $"Player {winningCard.Owner + 1} wins the trick! {trickPoints} points to Team {winningTeam + 1}"
    End Sub

    Private Function CalculateTrickPoints() As Integer
        Dim points As Integer = 0

        For Each card As Card In trick
            points += GetCardPoints(card)
        Next

        Return points
    End Function

    Private Function GetCardPoints(card As Card) As Integer
        ' Standard Klaverjassen point values
        Select Case card.Rank
            Case CardRank.Seven, CardRank.Eight, CardRank.Nine
                Return 0
            Case CardRank.Ten
                Return 10
            Case CardRank.Jack
                Return 2
            Case CardRank.Queen
                Return 3
            Case CardRank.King
                Return 4
            Case CardRank.Ace
                Return 11
            Case Else
                Return 0
        End Select
    End Function

    Private Function GetCardValue(card As Card) As Integer
        ' For comparison, not points
        Dim baseValue As Integer = CInt(card.Rank)

        ' In Klaverjassen, Jack of trump is highest
        If card.Suit = trumpSuit AndAlso card.Rank = CardRank.Jack Then
            Return 100
        End If

        ' 9 of trump is second highest
        If card.Suit = trumpSuit AndAlso card.Rank = CardRank.Nine Then
            Return 90
        End If

        Return baseValue
    End Function

    Private Function DetermineNextPlayer() As Integer
        ' Simple: winner of last trick starts next trick
        ' In a real game, you'd track who won the last trick
        Return 0 ' For simplicity, always human starts
    End Function

    Private Sub StartGame_Click(sender As Object, e As EventArgs)
        gameStarted = True
        startButton.Enabled = False
        startButton.Text = "Game in Progress"

        DealCards()
        DisplayPlayerHands()
        currentPlayer = 0 ' Human starts

        UpdateStatus()
    End Sub

    Private Sub UpdateStatus()
        statusLabel.Text = $"Current Player: {currentPlayer + 1} | "
        statusLabel.Text &= $"Team 1: {players(0).Score + players(2).Score} | "
        statusLabel.Text &= $"Team 2: {players(1).Score + players(3).Score}"

        ' Check for game end (all cards played)
        If players(0).Hand.Count = 0 Then
            EndGame()
        End If
    End Sub

    Private Sub EndGame()
        gameStarted = False
        startButton.Enabled = True
        startButton.Text = "New Game"

        Dim team1Score As Integer = players(0).Score + players(2).Score
        Dim team2Score As Integer = players(1).Score + players(3).Score

        Dim winner As String = If(team1Score > team2Score, "Team 1", "Team 2")

        MessageBox.Show($"Game Over!{vbCrLf}{vbCrLf}" &
                       $"Team 1: {team1Score} points{vbCrLf}" &
                       $"Team 2: {team2Score} points{vbCrLf}{vbCrLf}" &
                       $"{winner} wins!", "Game Finished", MessageBoxButtons.OK, MessageBoxIcon.Information)
    End Sub

    Private Function GetCardSymbol(card As Card) As String
        Dim rankSymbol As String = ""

        Select Case card.Rank
            Case CardRank.Jack
                rankSymbol = "J"
            Case CardRank.Queen
                rankSymbol = "Q"
            Case CardRank.King
                rankSymbol = "K"
            Case CardRank.Ace
                rankSymbol = "A"
            Case Else
                rankSymbol = CInt(card.Rank).ToString()
        End Select

        Dim suitSymbol As String = ""

        Select Case card.Suit
            Case CardSuit.Clubs
                suitSymbol = "♣"
            Case CardSuit.Spades
                suitSymbol = "♠"
            Case CardSuit.Hearts
                suitSymbol = "♥"
            Case CardSuit.Diamonds
                suitSymbol = "♦"
        End Select

        Return rankSymbol & vbCrLf & suitSymbol
    End Function

    Private Function GetSuitColor(suit As CardSuit) As Color
        Select Case suit
            Case CardSuit.Hearts, CardSuit.Diamonds
                Return Color.Red
            Case Else
                Return Color.Black
        End Select
    End Function

End Class
