/* Useful imports */

import edu.neu.ccs.*;
import edu.neu.ccs.gui.*;
import edu.neu.ccs.codec.*;
import edu.neu.ccs.console.*;
import edu.neu.ccs.filter.*;
import edu.neu.ccs.jpf.*;
import edu.neu.ccs.parser.*;
import edu.neu.ccs.pedagogy.*;
import edu.neu.ccs.quick.*;
import edu.neu.ccs.util.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.font.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.border.*;
import java.io.*;
import java.util.*;
import java.math.*;
import java.beans.*;
import java.lang.reflect.*;
import java.net.URL;
import java.util.regex.*;
import java.text.ParseException;


public class Sudoku
    extends TablePanel
    // implements ConsoleAware
{
    /** The small gap. */
    private static final int smallgap = 8;
    
    /** The medium gap. */
    private static final int mediumgap = 16;
    
    /** The large gap. */
    private static final int largegap = 48;
    
    
    /** The model object. */
    private SudokuModel model = new SudokuModel(this);
    
    /** The table object. */
    private SudokuTable table = model.getSudokuTable();
    
    /** The file IO tool. */
    private StringableFileIO fileIO =
        new StringableFileIO(model, "sudoku");
    
    
    /** The action showHints. */
    private SimpleAction showHints = model.getShowHints();
    
    /** The action clearHints. */
    private SimpleAction clearHints = model.getClearHints();
    
    /** The action resetHints. */
    private SimpleAction resetHints = model.getResetHints();
    
    /** The check box to select auto show hints. */
    private BooleanView autoShowHints =
        new BooleanView("Show Hints Automatically?", false);
    
    
    /** The IO stuff. */
    private Object[] hintsStuff =
        { showHints, clearHints, resetHints, autoShowHints };
    
    /** The IO panel. */
    private TablePanel hintsPanel =
        new TablePanel
            (hintsStuff, VERTICAL, smallgap, smallgap, CENTER);
    
    
    /** The action pruneOneCycle. */
    private SimpleAction pruneOneCycle = model.getPruneOneCycle();
    
    /** The action pruneComplete. */
    private SimpleAction pruneComplete = model.getPruneComplete();
    
    
    /** The check box for the prune triplets algorithm. */
    private BooleanView pruneTriplets =
        new BooleanView("Prune Triplets?", false);
    
    /** The check box for the prune triplets algorithm. */
    private BooleanView pruneHintSets =
        new BooleanView("Prune Hint Sets?", false);
    
    /** The check box for the prune triplets algorithm. */
    private BooleanView pruneUniqueHints =
        new BooleanView("Prune Unique Hints?", false);
    
    
    /** The Prune Choice stuff. */
    private Object[] pruneChoiceStuff =
        { pruneTriplets, pruneHintSets, pruneUniqueHints };
    
    /** The Prune Choice panel. */
    private TablePanel pruneChoicePanel =
        new TablePanel
            (pruneChoiceStuff, VERTICAL, smallgap, smallgap, WEST);
    
    
    /** The paint swatch to signal pruning. */
    private PaintSwatch swatch = new PaintSwatch(Colors.white);
    
    /** The signal stuff. */
    private Object[] signalStuff =
        { "Has Pruned?", swatch };
    
    /** The signal table. */
    private TablePanel signalPanel =
        new TablePanel
            (signalStuff, HORIZONTAL, smallgap, smallgap, CENTER);
    
    
    /** The check box to select auto prune hints. */
    private BooleanView autoPruneHints =
        new BooleanView("Prune Hints Automatically?", false);
    
    
    /** The Prune stuff. */
    private Object[] pruneStuff =
        { pruneOneCycle, pruneComplete, pruneChoicePanel,
          signalPanel, autoPruneHints };
    
    
    /** The Prune panel. */
    private TablePanel prunePanel =
        new TablePanel
            (pruneStuff, VERTICAL, smallgap, smallgap, CENTER);
    
    
    
    /** The action to read from a file. */
    private final SimpleAction readFromFile =
        new SimpleAction("Read Sudoku From File") {
            public void perform() {
                if (fileIO.readDataFromFile())
                    model.updateHints();
            }
    };
    
    
    /** The action to save to a file. */
    private final SimpleAction saveToFile =
        new SimpleAction("Save Sudoku To File") {
            public void perform() {
                fileIO.saveDataToFile();
            }
    };
    
    
    
    
    /** The IO stuff. */
    private Object[] IOStuff =
        { readFromFile, saveToFile };
    
    /** The IO panel. */
    private TablePanel IOPanel =
        new TablePanel
            (IOStuff, VERTICAL, smallgap, smallgap, CENTER);
    
    
    /** The action to make a new Sudoku puzzle. */
    private SimpleAction newSudoku =
        new SimpleAction("New Sudoku Puzzle") {
            public void perform() { new Sudoku(); }
    };
    
    
    /** The action to remove everything. */
    private SimpleAction removeEverything = model.getRemoveEverything();
    
    
    /** The controls stuff. */
    private Object[] controlsStuff =
        { hintsPanel, prunePanel, IOPanel, removeEverything, newSudoku };
    
    /** The controls table. */
    private TablePanel controlsPanel =
        new TablePanel
            (controlsStuff, VERTICAL, largegap, largegap, CENTER);
    
    
    /** The constructor. */
    public Sudoku() {
        super(1, 2, mediumgap, mediumgap, NORTH);
        
        initialize();
    }
    
    
    /** Returns whether or not to do auto show hints. */
    public boolean doAutoShowHints() {
        return autoShowHints.getBooleanValue();
    }
    
    
    /** Returns whether or not to prune triplets. */
    public boolean doPruneTriplets() {
        return pruneTriplets.getBooleanValue();
    }
    
    
    /** Returns whether or not to do prune hint sets. */
    public boolean doPruneHintSets() {
        return pruneHintSets.getBooleanValue();
    }
    
    
    /** Returns whether or not to do auto hints. */
    public boolean doPruneUniqueHints() {
        return pruneUniqueHints.getBooleanValue();
    }
    
    
    /** Returns whether or not to do auto prune hints. */
    public boolean doAutoPruneHints() {
        return autoPruneHints.getBooleanValue();
    }
    
    
    /**
     * Set the swatch signal to red if the given flag is true
     * and to white if the given flag is false.
     */
    public void setSignal(boolean flag) {
        if (flag)
            swatch.setPaint(Colors.red);
        else
            swatch.setPaint(Colors.white);
    }
    
    
    /** The constructor initialize method. */
    private void initialize() {
        // console.setActivated(true);
        
        addObject(controlsPanel, 0, 0);
        addObject(table, 0, 1);
        
        int g = mediumgap;
        setBorder(BorderFactory.createEmptyBorder(g, g, g, g));
        
        frame("Sudoku Puzzle");
    }
    
    
    /** The main method. */
    public static void main(String[] args) {
        new Sudoku();
    }

}

