/*
 * Copyright (c) 2002-2007 TeamDev Ltd. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * The complete licence text can be found at
 * http://www.jniwrapper.com/pages/macpack/license
 */
package com.jniwrapper.macosx.samples.demo;

import com.jniwrapper.samples.shell.components.LazyPanel;
import com.jniwrapper.samples.shell.components.HTMLText;
import com.jniwrapper.unix.system.io.FileSystemEventListener;
import com.jniwrapper.unix.system.io.FileSystemWatcher;
import com.jniwrapper.unix.system.io.FileSystemEvent;
import com.jniwrapper.util.Logger;
import com.jniwrapper.macosx.ui.controls.SelectFolderField;
//import com.jniwrapper.macosx.ui.controls.SelectFolderField;

import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 @author Vadim Steshenko
 */
public class FileSystemWatcherSample extends LazyPanel
        implements ActionListener, FileSystemEventListener, PropertyChangeListener
{
    private static final Logger LOG = Logger.getInstance(FileSystemWatcherSample.class);

    static final String[] ACTION_NAMES = new String[]{"added""removed""modified""renamed"};
    static final String MESSAGE_TEMPLATE = "File ''{0}'' was ''{1}''";

    static final String SHORT_DATE_FORMAT = "HH:mm:ss";
    static final String LONG_DATE_FORMAT = "dd/MM/yyyy HH:ss:mm";

    private JLabel lblAdvisoryText;
    private JLabel lblSelectFolderCaption;
    private SelectFolderField _selectFolderField;
    private JCheckBox chkWatchSubtree;
    private JCheckBox chkChangeFileName;
    private JCheckBox chkChangeDirName;
    private JList lstEvents;
    private DefaultListModel _listModel;
    private JLabel lblEvents;
    private FileSystemWatcher _fileSystemWatcher;
    private JButton btnStart;
    private JButton btnStop;

    public FileSystemWatcherSample(Window parent)
    {
        super(parent);
    }

    public void initialize() throws Exception
    {
        lblAdvisoryText = new HTMLText("This sample demonstrates FileSystemWatcher class features.");
        lblSelectFolderCaption = new JLabel("Watching Folder:");
        chkWatchSubtree = new JCheckBox("Watch Subtree"true);
        chkChangeFileName = new JCheckBox("Watch File Name Change"true);
        chkChangeDirName = new JCheckBox("Watch Dir Name Change"true);
        _selectFolderField = new SelectFolderField();
        _selectFolderField.addPropertyChangeListener(SelectFolderField.PROPERTY_FOLDER, this);

        lblEvents = new JLabel("File System Events:");
        _listModel = new DefaultListModel();
        lstEvents = new JList(_listModel);
        btnStart = new JButton("Start");
        btnStart.setEnabled(false);
        btnStart.addActionListener(this);
        btnStop = new JButton("Stop");
        btnStop.setEnabled(false);
        btnStop.addActionListener(this);

        setLayout(new GridBagLayout());

        JScrollPane eventPane = new JScrollPane(lstEvents);
        Dimension preferredSize = new Dimension(200100);
        eventPane.setPreferredSize(preferredSize);
        eventPane.setMinimumSize(preferredSize);

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(btnStart);
        buttonPanel.add(btnStop);

        add(lblAdvisoryText, new GridBagConstraints(00210.00.0,
                GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10101010)00));
        add(lblSelectFolderCaption, new GridBagConstraints(01110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10101010)00));
        add(_selectFolderField, new GridBagConstraints(11110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(10101010)00));
        add(chkWatchSubtree, new GridBagConstraints(02110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(31000)00));
        add(chkChangeFileName, new GridBagConstraints(03110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(31000)00));
        add(chkChangeDirName, new GridBagConstraints(13110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(35010)00));
        add(lblEvents, new GridBagConstraints(05110.00.0,
                GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1010010)00));
        add(eventPane, new GridBagConstraints(06211.01.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0000)00));
        add(buttonPanel, new GridBagConstraints(17110.00.0,
                GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(010010)00));
        add(new JPanel()new GridBagConstraints(08211.01.0,
                GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0000)00));

        super.initialize();
    }

    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource().equals(btnStart))
        {
            startWatching();
        }
        else if (e.getSource().equals(btnStop))
        {
            stopWatching();
        }
    }

    private void startWatching()
    {
        _listModel.clear();
        _fileSystemWatcher = new FileSystemWatcher(_selectFolderField.getFolder(), chkWatchSubtree.isSelected());
        _fileSystemWatcher.addFileSystemListener(this);

        btnStart.setEnabled(false);
        btnStop.setEnabled(true);

        try
        {
            _fileSystemWatcher.start();
            _listModel.addElement("Start at " + getDateTime(true));
            lstEvents.setSelectedIndex(0);
        }
        catch (Exception e)
        {
            LOG.error("", e);
            JOptionPane.showMessageDialog(this, "Unable to start watcher.\n"+ e, "File System Watcher", JOptionPane.WARNING_MESSAGE);
            btnStart.setEnabled(true);
            btnStop.setEnabled(false);
        }
    }

    private void stopWatching()
    {
        _listModel.addElement("Stop at " + getDateTime(true));
        final int size = _listModel.getSize() 1;
        lstEvents.setSelectedIndex(size);
        lstEvents.ensureIndexIsVisible(size);

        btnStart.setEnabled(true);
        btnStop.setEnabled(false);

        try
        {
            _fileSystemWatcher.stop();
        }
        catch(Exception e)
        {
            LOG.error("", e);
        }
    }

    public void deactivate()
    {
        if (_fileSystemWatcher != null && _fileSystemWatcher.isWatching())
        {
            stopWatching();
        }
    }

    public void handle(FileSystemEvent event)
    {
        String actionName = ACTION_NAMES[event.getAction()];
        String message = MessageFormat.format(MESSAGE_TEMPLATE, new Object[]{event.getFileName(), actionName});
        if (event.getAction() == FileSystemEvent.RENAMED)
            message += " from '" + event.getOldFileName() "'";
        message += " at " + getDateTime(false);

        _listModel.addElement(message);
        final int size = _listModel.getSize() 1;
        lstEvents.setSelectedIndex(size);
        lstEvents.ensureIndexIsVisible(size);
    }

    String getDateTime(boolean longFormat)
    {
        SimpleDateFormat dateFormat = new SimpleDateFormat(longFormat ? LONG_DATE_FORMAT : SHORT_DATE_FORMAT);
        return dateFormat.format(new Date());
    }

    public void propertyChange(PropertyChangeEvent evt)
    {
        btnStart.setEnabled(true);
    }
}