
package uk.co.wingpath.modbusgui;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import uk.co.wingpath.util.*;
import uk.co.wingpath.xml.*;
import uk.co.wingpath.gui.*;

public class ConfigurationFile
{
    private final WFileChooser fileChooser;
    private final Settings settings;
    private final Registers registers;
    private final FileRegisters fileRegisters;
    private final Product product;
    private final StatusBar statusBar;
    private final Reporter reporter;
    private final Frontend frontend;
    private final WFrame mainFrame;

    public ConfigurationFile (Settings settings, Product product,
        Frontend frontend, Reporter reporter)
    {
        if (reporter == null)
            throw new NullPointerException ("reporter must not be null");
        this.settings = settings;
        this.product = product;
        this.frontend = frontend;
        this.reporter = reporter;
        mainFrame = frontend.getMainFrame ();
        statusBar = frontend.getStatusBar ();
        registers = settings.getRegisters ();
        fileRegisters = settings.getFileRegisters ();
        fileChooser = new WFileChooser (mainFrame);
    }

    private void loadConfigurationFile (File file)
        throws ValueException, IOException
    {
        Xml.load ("modsak", settings.getXmlLoader (reporter), file);
    }

    public File backupConfiguration ()
    {
        try
        {
            File tempFile = File.createTempFile (product.getName (), null);
            if (!saveConfigurationFile (tempFile))
            {
                tempFile.delete ();
                return null;
            }
            return tempFile;
        }
        catch (IOException e)
        {
            return null;
        }
    }

    public void restoreConfiguration (File tempFile)
    {
        if (tempFile != null)
        {
            if (registers != null)
                registers.deleteAll ();
            if (fileRegisters != null)
                fileRegisters.deleteAllFiles ();
            settings.getCommands ().deleteAll ();
            try
            {
                loadConfigurationFile (tempFile);
            }
            catch (Exception e1)
            {
            }
        }
    }

    public boolean loadAndCheckConfigurationFile (File file)
    {
        if (file.isDirectory ())
        {
            fileChooser.setCurrentDirectory (file);
            return true;
        }
        fileChooser.setSelectedFile (file);
        File tempFile = backupConfiguration ();
        try
        {
            loadConfigurationFile (file);
            if (registers != null)
                registers.checkModel ();
            if (fileRegisters != null)
                fileRegisters.checkRegisters ();
        }
        catch (ValueException e)
        {
            restoreConfiguration (tempFile);
            reporter.error (null, 
                "Can't load from %s\n%s", file.getPath (), e.getMessage ());
            return false;
        }
        catch (IOException e)
        {
            // IOExceptions (sometimes?) include the filename in their messages,
            // so don't repeat it.
            restoreConfiguration (tempFile);
            reporter.error (null, "Can't load configuration\n%s",
                Exceptions.getMessage (e));
            return false;
        }
        finally
        {
            if (tempFile != null)
                tempFile.delete ();
        }

        reporter.info (null, "Configuration loaded from %s", file.getPath ());
        return true;
    }

    public void loadConfiguration ()
    {
        reporter.clear ();
        final File file = fileChooser.chooseLoadFile (
            product.getName () + ": Load Configuration",
            "Load",
            "Load configuration from selected file");
        if (file != null)
        {
            statusBar.clear ();
            statusBar.showMessage ("Loading configuration ...");
            EventQueue.invokeLater (new Runnable ()
                {
                    public void run ()
                    {
                        mainFrame.setCursor (
                            Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR));
                        loadAndCheckConfigurationFile (file);
                        mainFrame.setCursor (Cursor.getDefaultCursor ());
                    }
                });
        }
    }

    private boolean saveConfigurationFile (File file)
    {
        try
        {
            Xml.save ("modsak", settings, file);
            return true;
        }
        catch (IOException e)
        {
            reporter.error (null, "Can't save configuration\n%s",
                Exceptions.getMessage (e));
        }

        return false;
    }

    public void saveConfiguration ()
    {
        reporter.clear ();
        final File file = fileChooser.chooseSaveFile (
            product.getName () + ": Save Configuration",
            "Save",
            "Save configuration to selected file");
        if (file != null)
        {
            statusBar.clear ();
            statusBar.showMessage ("Saving configuration ...");
            EventQueue.invokeLater (new Runnable ()
                {
                    public void run ()
                    {
                        mainFrame.setCursor (
                            Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR));
                        try
                        {
                            if (saveConfigurationFile (file))
                            {
                                reporter.info (null, 
                                    "Configuration saved to %s",
                                    file.getPath ());
                            }
                        }
                        finally
                        {
                            mainFrame.setCursor (Cursor.getDefaultCursor ());
                        }
                    }
                });
        }
    }
}

