package de.duehl.swing.start;

/*
 * Copyright 2017 Christian Dühl. All rights reserved.
 *
 * This program is free software. You can redistribute it and/or
 * modify it under the same terms as perl:
 *
 * general:  http://dev.perl.org/licenses/
 * GPL:      http://dev.perl.org/licenses/gpl1.html
 * artistic: http://dev.perl.org/licenses/artistic.html
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;

import de.duehl.basics.io.FileHelper;
import de.duehl.basics.io.lock.FileLock;
import de.duehl.swing.ui.GuiTools;
import de.duehl.swing.ui.handler.error.SimpleErrorHandler;

/**
 * Diese Klasse testet den Locker.
 *
 * Sie ist nicht unter .../test, damit sie aus dem Jar-File auf anderen Rechnern aufgerufen werden
 * kann.
 *
 * @version 1.01     2017-03-27
 * @author Christian Dühl
 */

public class LockTester {

    private static final Dimension BUTTON_SIZE = new Dimension(200, 200);

    private FileLock lock;

    private final JFrame frame;
    private final SimpleErrorHandler error;
    private final JTextField reportField;
    private final JTextField filenameField;
    private final JCheckBox weHaveTheLockCheckBox;

    public LockTester() {
        this("c:\\temp\\lock_test.lock");
    }

    private LockTester(String filename) {
        lock = new FileLock(filename);
        GuiTools.setNiceLayoutManager();
        frame = new JFrame();
        reportField = new JTextField();
        filenameField = new JTextField();
        weHaveTheLockCheckBox = new JCheckBox();


        Image programImage = null;
        error = new SimpleErrorHandler(programImage, frame);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createGui();
            }
        });
    }

    /** Erstellt die grafische Oberfläche und zeigt sie an. */
    private void createGui() {
        frame.setTitle("Lock Tester");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        frame.add(createDetermineLockFile(), BorderLayout.NORTH);
        frame.add(createReportArea(), BorderLayout.CENTER);
        frame.add(createButtons(), BorderLayout.SOUTH);

        frame.pack();
    }

    private Component createDetermineLockFile() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createFileNameTitle(), BorderLayout.WEST);
        panel.add(createFilenameTextField(), BorderLayout.CENTER);
        panel.add(createChangeFilenameButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createFileNameTitle() {
        return new JLabel("Lock-Datei: ");
    }

    private Component createFilenameTextField() {
        filenameField.setText(lock.getFilename());
        return filenameField;
    }

    private Component createChangeFilenameButton() {
        JButton button = new JButton("ändern");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                changeFilename();
            }
        });
        return button;
    }

    private void changeFilename() {
        String filename = askForFilename();
        if (filename.isEmpty()) {
            report("Abbruch durch den Benutzer. Lock-Datei bleibt: " + filename);
        }
        else {
            setFilename(filename);
        }
    }

    private void setFilename(String filename) {
        lock = new FileLock(filename);
        filenameField.setText(filename);
        report("Neue Lock-Datei: " + filename);
    }

    private String askForFilename() {
        String oldLockFilename = lock.getFilename();
        File oldLockFile = new File(oldLockFilename);
        if (!oldLockFile.exists()) {
            oldLockFile = new File(FileHelper.getDirName(oldLockFilename));
        }
        FileFilter filter = GuiTools.createLockFileFilter();
        return GuiTools.openFile(frame, oldLockFile, filter);
    }

    private Component createReportArea() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createReportField(), BorderLayout.NORTH);
        panel.add(createShowLockPart(), BorderLayout.SOUTH);

        return panel;
    }

    private Component createReportField() {
        report("");
        return reportField;
    }

    private Component createShowLockPart() {
        unLocked();
        return weHaveTheLockCheckBox;
    }

    private void locked() {
        weHaveTheLockCheckBox.setEnabled(true);
        weHaveTheLockCheckBox.setSelected(true);
        weHaveTheLockCheckBox.setText("Wir haben den Lock");
        weHaveTheLockCheckBox.setForeground(new Color(0x00, 0x80, 0x00));
        weHaveTheLockCheckBox.setEnabled(false);
        weHaveTheLockCheckBox.revalidate();
    }

    private void unLocked() {
        weHaveTheLockCheckBox.setEnabled(true);
        weHaveTheLockCheckBox.setSelected(false);
        weHaveTheLockCheckBox.setText("Wir haben keinen Lock.");
        weHaveTheLockCheckBox.setForeground(Color.RED);
        weHaveTheLockCheckBox.setEnabled(false);
        weHaveTheLockCheckBox.revalidate();
    }

    private void report(String text) {
        reportField.setText(text);
    }

    private Component createButtons() {
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createLockButton(), BorderLayout.WEST);
        panel.add(createReleaseButton(), BorderLayout.EAST);

        return panel;
    }

    private Component createLockButton() {
        JButton button = new JButton("LOCK");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                lock();
            }
        });
        button.setPreferredSize(BUTTON_SIZE);
        return button;
    }

    private Component createReleaseButton() {
        JButton button = new JButton("RELEASE");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                release();
            }
        });
        button.setPreferredSize(BUTTON_SIZE);
        return button;
    }

    private void lock() {
        try {
            tryToLock();
        }
        catch (Exception exception) {
            report("Fehler beim Lock: " + exception.getMessage());
            error.error("Fehler beim Lock", exception);
        }
    }

    private void tryToLock() {
        boolean success = lock.lock();
        if (success) {
            report("Lock erhalten");
            locked();
        }
        else {
            report("Lock NICHT erhalten");
        }
    }

    private void release() {
        try {
            tryToRelease();
        }
        catch (Exception exception) {
            report("Fehler beim Release: " + exception.getMessage());
            error.error("Fehler beim Release", exception);
        }
    }

    private void tryToRelease() {
        boolean success = lock.unlock();
        if (success) {
            report("Lock gelöst");
            unLocked();
        }
        else {
            report("Lock NICHT gelöst");
        }
    }

    protected void setVisible(boolean visible) {
        frame.setVisible(visible);
    }

    public static void main(String[] args) {
        new LockTester().setVisible(true);
    }

}
