/* 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 StringableFileIO

{
    /** The stringable model to read or save via this class. */
    private Stringable model = null;
    
    
    /**
     * The file extension to associate with this model.
     * 
     * Do not include the period character.
     */
    private String extension = null;
    
    
    /** The file filter for file I/O. */
    private FileExtensionFilter modelFileFilter = null;
    
    
    /** Initialization for home directory as directory ".". */
    private File home = new File(".");
    
    
    /** The file chooser used for file I/O. */
    private JFileChooser filechooser = new JFileChooser();
    
    
    /**
     * The constructor that provides the Stringable model to read
     * or save via this class and its file extension.
     * 
     * Throws NullPointerException if the model is null.
     * 
     * Uses "txt" as the extension if the given extension is null.
     * 
     * @param model the Stringable model requiring file IO
     * @param extension the file extension to use for model files
     */
    public StringableFileIO(Stringable model, String extension) {
        if (model == null)
            throw new NullPointerException
                ("Null model passed to StringableFileIO constructor");
        
        this.model = model;
        this.extension = (extension != null) ? extension : "txt";
        
        modelFileFilter = new FileExtensionFilter(extension);
        
        filechooser.setFileFilter(modelFileFilter);
        filechooser.setCurrentDirectory(home);
    }
    
    
    /**
     * <p>Opens a file dialog to get the file name of a text file
     * with model data and then reads the data.<p>
     *
     * <p>Does nothing to the current data if errors occur.</p>
     *
     * @return true if the operation succeeds
     */
    public boolean readDataFromFile()
    {
        int result = filechooser.showOpenDialog(null);
        
        if (result == JFileChooser.CANCEL_OPTION)
            return false;
        
        if (result == JFileChooser.ERROR_OPTION) {
            GeneralDialog.showOKDialog
                ("File Read Error", "File Read Error");
            
            return false;
        }
        
        File source = filechooser.getSelectedFile();
        
        filechooser.setCurrentDirectory(source);
        
        return readDataFromFile(source, true);
    }
    
    
    /**
     * <p>Reads the model data from the given text file.<p>
     *
     * <p>Does nothing to the current data if errors occur.</p>
     *
     * @param source the data source
     * @param displayErrorDialogs if true display error dialogs
     *
     * @return true if the operation succeeds
     */
    public boolean readDataFromFile
        (File source, boolean displayErrorDialogs)
    {
        if (source == null) {
             if (displayErrorDialogs) {
                String message =
                    "Error in reading file\n"
                    + "Null source File object\n";
                
                GeneralDialog.showOKDialog
                    (message, "File Read Error");
            }
            
           return false;
        }
        
        String data = "";
        
        try {
            data = FileUtilities.readFile(source);
        }
        catch (Exception ex) {
            if (displayErrorDialogs) {
                String message =
                    "Error in reading file\n"
                    + source.getName() + "\n\n"
                    + ex.getMessage() + "\n";
                
                GeneralDialog.showOKDialog
                    (message, "File Read Error");
            }
            
            return false;
        }
        
        try {
            model.fromStringData(data);
        }
        catch (ParseException ex) {
            if (displayErrorDialogs) {
                String message =
                    "Error in reading file\n"
                    + source.getName() + "\n\n"
                    + ex.getMessage() + "\n";
                
                GeneralDialog.showOKDialog
                    (message, "File Read Error");
            }
            
            return false;
        }
        
        return true;
    }
    
    
    /**
     * <p>Opens a file dialog to get the file name of a model file
     * and then saves the data to the file.<p>
     *
     * <p>Does nothing if errors occur.</p>
     *
     * @return true if the operation succeeds
     */
    public boolean saveDataToFile()
    {
        int result = filechooser.showSaveDialog(null);
        
        if (result == JFileChooser.CANCEL_OPTION)
            return false;
        
        if (result == JFileChooser.ERROR_OPTION) {
            GeneralDialog.showOKDialog
                ("File Save Error", "File Save Error");
            
            return false;
        }
        
        File target = filechooser.getSelectedFile();
        String path = target.getPath();
        
        if (! modelFileFilter.accept(target)) {
            path += "." + extension;
            target = new File(path);
        }
        
        filechooser.setCurrentDirectory(target);
        
        return saveDataToFile(target, true);
    }
    
    
    /**
     * <p>Saves the sudoku data to the given model file.<p>
     *
     * <p>Does nothing if errors occur.</p>
     *
     * @param target the data target
     * @param displayErrorDialogs if true display error dialogs
     * @return true if the operation succeeds
     */
    public boolean saveDataToFile
        (File target, boolean displayErrorDialogs)
    {
        if (target == null) {
             if (displayErrorDialogs) {
                String message =
                    "Error in writing file\n"
                    + "Null target File\n";
                
                GeneralDialog.showOKDialog
                    (message, "File Save Error");
            }
            
           return false;
        }
        
        String data = model.toString();
        
        try {
            FileUtilities.writeFile(target, data, true);
        }
        catch (Exception ex) {
            if (displayErrorDialogs) {
                String message =
                    "Error in writing file\n"
                    + target.getName() + "\n\n"
                    + ex.getMessage() + "\n";
                
                GeneralDialog.showOKDialog
                    (message, "File Save Error");
            }
            
            return false;
        }
        
        return true;
    }
    
}

