import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FlagGUI extends JFrame
{
    private JComboBox<String> flagSelector;
    private JPanel canvasPanel;
    private char[][] currentMatrix;

    private static final int TRICOLOR_WIDTH = 30;
    private static final int TRICOLOR_HEIGHT = 12;
    private static final int ADVANCED_WIDTH = 44;
    private static final int ADVANCED_HEIGHT = 32;

    public FlagGUI()
    {
        setTitle("Museum Matrix Flag Exhibition");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        // Control Panel
        JPanel controlPanel = new JPanel();
        controlPanel.setBorder(BorderFactory.createTitledBorder("Exhibition Selector"));
        
        String[] flags = {
            "Select a Flag...", 
            "France (Vertical)", 
            "Italy (Vertical)", 
            "Germany (Horizontal)", 
            "Armenia (Horizontal)",
            "Revolutionary War Flag (Extra Credit)",
            "Norway (Extra Credit)"
        };
        
        flagSelector = new JComboBox<>(flags);
        flagSelector.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                updateFlagCanvas();
            }
        });
        
        controlPanel.add(new JLabel("Choose Canvas: "));
        controlPanel.add(flagSelector);
        add(controlPanel, BorderLayout.NORTH);

        // 1. The Museum Gallery Wall Background
        JPanel exhibitionCenter = new JPanel(new BorderLayout());
        exhibitionCenter.setBackground(new Color(238, 235, 225)); // Warm Cream Museum Wall Tone
        
        // This margin scrunches the frame inward, revealing the gallery wall on the edges
        exhibitionCenter.setBorder(BorderFactory.createEmptyBorder(30, 40, 30, 40));

        // 2. Core Drawing Canvas Component
        canvasPanel = new JPanel()
        {
            @Override
            protected void paintComponent(Graphics g)
            {
                super.paintComponent(g);
                
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                
                drawMatrixPixels(g2d);
            }
        };
        
        canvasPanel.setPreferredSize(new Dimension(800, 450));
        canvasPanel.setBackground(new Color(25, 25, 25));
        
        // 3. Multi-Layered 3D Picture Frame Complex
        canvasPanel.setBorder(BorderFactory.createCompoundBorder(
            // Layer A: Outer Frame Drop Shadow (Simulating ambient occluded wall depth)
            BorderFactory.createLineBorder(new Color(0, 0, 0, 40), 5),
            BorderFactory.createCompoundBorder(
                // Layer B: Lighter, Warm Honey Oak / Light Walnut Wood Outer Lip
                BorderFactory.createLineBorder(new Color(155, 100, 50), 14), 
                BorderFactory.createCompoundBorder(
                    // Layer C: Gold Gilt Accent Trim bevel highlighting inner shadow drop
                    BorderFactory.createBevelBorder(BevelBorder.LOWERED, new Color(155, 120, 70), new Color(105, 75, 40)),
                    // Layer D: Micro internal gap matrix seal
                    BorderFactory.createEmptyBorder(1, 1, 1, 1)
                )
            )
        ));

        exhibitionCenter.add(canvasPanel, BorderLayout.CENTER);
        add(exhibitionCenter, BorderLayout.CENTER);

        pack();
        setResizable(true); 
        setLocationRelativeTo(null);
    }

    private void updateFlagCanvas()
    {
        String selection = (String) flagSelector.getSelectedItem();
        
        if (selection.equals("France (Vertical)"))
        {
            currentMatrix = FlagCanvas.frenchFlag(TRICOLOR_WIDTH, TRICOLOR_HEIGHT);
        }
        else if (selection.equals("Italy (Vertical)"))
        {
            currentMatrix = FlagCanvas.italianFlag(TRICOLOR_WIDTH, TRICOLOR_HEIGHT);
        }
        else if (selection.equals("Germany (Horizontal)"))
        {
            currentMatrix = FlagCanvas.germanFlag(TRICOLOR_WIDTH, TRICOLOR_HEIGHT);
        }
        else if (selection.equals("Armenia (Horizontal)"))
        {
            currentMatrix = FlagCanvas.armenianFlag(TRICOLOR_WIDTH, TRICOLOR_HEIGHT);
        }
        else if (selection.equals("Revolutionary War Flag (Extra Credit)"))
        {
            currentMatrix = FlagCanvas.revolutionaryFlag();
        }
        else if (selection.equals("Norway (Extra Credit)"))
        {
            currentMatrix = FlagCanvas.norwegianFlag(ADVANCED_WIDTH, ADVANCED_HEIGHT);
        }
        else
        {
            currentMatrix = null;
        }
        
        canvasPanel.repaint();
    }

    private void drawMatrixPixels(Graphics2D g)
    {
        if (currentMatrix == null)
        {
            g.setColor(Color.LIGHT_GRAY);
            g.setFont(new Font("SansSerif", Font.ITALIC, 16));
            g.drawString("Please select an exhibit from the menu above.", 230, 225);
            return;
        }

        int rows = currentMatrix.length;
        int cols = currentMatrix[0].length;
        
        Insets frameInsets = canvasPanel.getInsets();
        int renderWidth = canvasPanel.getWidth() - frameInsets.left - frameInsets.right;
        int renderHeight = canvasPanel.getHeight() - frameInsets.top - frameInsets.bottom;

        double colWidthStep = (double) renderWidth / cols;
        double rowHeightStep = (double) renderHeight / rows;

        for (int r = 0; r < rows; r++)
        {
            int yStart = frameInsets.top + (int) (r * rowHeightStep);
            int yEnd = frameInsets.top + (int) ((r + 1) * rowHeightStep);
            int cellHeight = yEnd - yStart;
            
            if (r == rows - 1)
            {
                cellHeight = (frameInsets.top + renderHeight) - yStart;
            }

            for (int c = 0; c < cols; c++)
            {
                char token = currentMatrix[r][c];
                
                int xStart = frameInsets.left + (int) (c * colWidthStep);
                int xEnd = frameInsets.left + (int) ((c + 1) * colWidthStep);
                int cellWidth = xEnd - xStart;

                if (c == cols - 1)
                {
                    cellWidth = (frameInsets.left + renderWidth) - xStart;
                }
                
                if (token == 'S')
                {
                    g.setColor(new Color(10, 49, 119));
                    g.fillRect(xStart, yStart, cellWidth, cellHeight);
                    
                    int centerX = xStart + (cellWidth / 2);
                    int centerY = yStart + (cellHeight / 2);
                    int radius = Math.min(cellWidth, cellHeight) / 2;
                    
                    g.setColor(Color.WHITE);
                    fill5PointedStar(g, centerX, centerY, radius);
                }
                else
                {
                    g.setColor(mapTokenToColor(token));
                    g.fillRect(xStart, yStart, cellWidth, cellHeight);
                }
            }
        }
    }

    private void fill5PointedStar(Graphics2D g, int cx, int cy, int maxRadius)
    {
        int outerRadius = maxRadius;
        int innerRadius = maxRadius / 2;
        
        int[] xPoints = new int[10];
        int[] yPoints = new int[10];
        
        double startAngle = -Math.PI / 2;
        double angleIncrement = Math.PI / 5;

        for (int i = 0; i < 10; i++)
        {
            double currentAngle = startAngle + (i * angleIncrement);
            int r;
            
            if (i % 2 == 0)
            {
                r = outerRadius;
            }
            else
            {
                r = innerRadius;
            }
            
            xPoints[i] = cx + (int) (Math.cos(currentAngle) * r);
            yPoints[i] = cy + (int) (Math.sin(currentAngle) * r);
        }

        g.fillPolygon(xPoints, yPoints, 10);
    }

    private Color mapTokenToColor(char token)
    {
        switch (token)
        {
            case 'B': return new Color(10, 49, 119);
            case 'W': return new Color(245, 245, 245);
            case 'R': return new Color(206, 17, 38);
            case 'G': return new Color(0, 146, 70);
            case 'K': return new Color(20, 20, 20);
            case 'Y': return new Color(255, 204, 0);
            case 'O': return new Color(242, 168, 73);
            default: return Color.DARK_GRAY;
        }
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new FlagGUI().setVisible(true);
            }
        });
    }
}