package gui;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

import sudoku.SudokuParser;

/**
 * SolverView is a GUI for the SudokuSolver interface
 */
public class SudokuView extends JFrame {
    /** The grid of text fields */
    private JTextField[][] grid;

    /** Button for solve */
    private JButton solveButton;
    /** Button for reset */
    private JButton resetButton;
    /** Button for random */
    private JButton randomButton;
    /** Button for picking a Sudoku-file */
    private JButton fileButton;

    /** Constructor */
    public SudokuView() {
        setTitle("Sudoku Solver");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        initializeGrid();
        initializeButtons();

        pack();
        setLocationRelativeTo(null);
    }

    /** Initialize the grid, called by the constructor */
    private void initializeGrid() {
        grid = new JTextField[9][9];
        JPanel gridPanel = new JPanel(new GridLayout(9, 9));

        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                grid[row][col] = new JTextField(2);
                grid[row][col].setHorizontalAlignment(JTextField.CENTER);
                gridPanel.add(grid[row][col]);
            }
        }

        add(gridPanel, BorderLayout.CENTER);
    }

    /** Initialize the buttons, called by the constructor */
    private void initializeButtons() {
        solveButton = new JButton("Solve");
        resetButton = new JButton("Reset");
        randomButton = new JButton("Randomize");
        fileButton = new JButton("Open file");

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(solveButton);
        buttonPanel.add(resetButton);
        buttonPanel.add(randomButton);
        buttonPanel.add(fileButton);

        add(buttonPanel, BorderLayout.SOUTH);
    }

    /**
     * Update the view with a new grid
     * 
     * @param newGrid the new grid to display
     */
    public void updateView(int[][] newGrid) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (newGrid[row][col] != 0) {
                    grid[row][col].setText(String.valueOf(newGrid[row][col]));
                } else {
                    grid[row][col].setText("");
                }
            }
        }
    }

    /**
     * Method to add ActionListener to solve button
     * 
     * @param listener the ActionListener to add
     */
    public void addSolveButtonListener(ActionListener listener) {
        solveButton.addActionListener(listener);
    }

    /**
     * Method to add ActionListener to reset button
     * 
     * @param listener the ActionListener to add
     */
    public void addResetButtonListener(ActionListener listener) {
        resetButton.addActionListener(listener);
    }

    /**
     * Method to add ActionListener to randomize button
     * 
     * @param listener the ActionListener to add
     */
    public void addRandomButtonListener(ActionListener listener) {
        randomButton.addActionListener(listener);
    }

    /**
     * Method to add ActionListener to file button
     * 
     * @param listener the ActionListener to add
     */
    public void addFileButtonListener(ActionListener listener) {
        fileButton.addActionListener(listener);
    }

    /**
     * Method to add ActionListener to individual cells in the grid
     * <p>
     * Assumes that the ActionListener will be the same for all cells
     * and that the listener will be capable of determining which cell
     * was clicked
     * 
     * @param listener the ActionListener to add
     */
    public void addCellActionListener(ActionListener listener) {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                grid[row][col].addActionListener(listener);
            }
        }
    }

    /**
     * Getter method to retrieve the values from the text fields
     * 
     * @param row the row of the cell
     * @param col the column of the cell
     * @return the value of the cell
     */
    public String getCellValue(int row, int col) {
        return grid[row][col].getText();
    }

    /**
     * Method to get the selected row (example implementation)
     * 
     * @return the selected row, or -1 if no cell is selected
     */
    public int getSelectedRow() {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (grid[row][col].isFocusOwner()) {
                    return row;
                }
            }
        }
        return -1; // Return -1 if no cell is selected
    }

    /**
     * Method to get the selected column (example implementation)
     * 
     * @return the selected row, or -1 if no cell is selected
     */
    public int getSelectedColumn() {
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (grid[row][col].isFocusOwner()) {
                    return col;
                }
            }
        }
        return -1; // Return -1 if no cell is selected
    }

    /**
     * Methods to show dialogs
     * 
     * @param message the message to display
     * @return the user input
     */
    public String showInputDialog(String message) {
        return JOptionPane.showInputDialog(this, message);
    }

    /**
     * Method to show error messages
     * 
     * @param message the message to display
     */
    public void showErrorMessage(String message) {
        JOptionPane.showMessageDialog(this, message);
    }

    /**
     * Method to open a file picker dialog
     * 
     * @return 2D array of integers representing the Sudoku board
     */
    public int[][] openFile() {
        // Create a file chooser and set all related options
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setCurrentDirectory(new java.io.File("."));
        fileChooser.setDialogTitle("Select a Sudoku file");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setAcceptAllFileFilterUsed(false);

        // Show the file chooser and return if the user cancels
        int returnValue = fileChooser.showOpenDialog(this);
        if (returnValue != JFileChooser.APPROVE_OPTION) {
            return null;
        }

        // Get the path
        String filepath = fileChooser.getSelectedFile().getAbsolutePath();

        // Try to parse it
        try {
            return SudokuParser.parseSudoku(filepath);
        } catch (Exception e) {
            showErrorMessage(e.getMessage());
            return null;
        }
    }
}