package de.duehl.swing.ui.dialogs.logging;

/*
 * Copyright 2020 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.Component;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.util.List;

import javax.swing.JPanel;

import de.duehl.basics.logging.LogEntry;
import de.duehl.swing.ui.colors.Colorizer;
import de.duehl.swing.ui.components.selections.LongStringSelection;
import de.duehl.swing.ui.components.selections.StringSelection;
import de.duehl.swing.ui.dialogs.base.ModalDialogBase;
import de.duehl.swing.ui.elements.navigator.NavigatorPanel;
import de.duehl.swing.ui.layout.VerticalLayout;

/**
 * Diese Klasse stellt einen Dialog zur Anzeige der Daten von einer Zeile eines Logfiles dar.
 *
 * @version 1.02     2020-01-17
 * @author Christian Dühl
 */

public class LogEntryDialog extends ModalDialogBase {

    private static final Dimension DIALOG_DIMENSION = new Dimension(800, 750);
    private static final int ELEMENT_HEIGHT = 30;
    public static final Dimension IGNORE_WIDTH_DIMENSION = new Dimension(1, ELEMENT_HEIGHT);

    private final List<LogEntry> entries;
    private int entryIndex;

    private final StringSelection dateSelection;
    private final StringSelection timeSelection;
    private final StringSelection classSelection;
    private final StringSelection methodSelection;
    private final StringSelection lineNumberSelection;
    private final LongStringSelection messageSelection;

    public LogEntryDialog(List<LogEntry> entries, int entryIndex, String logFileName,
            Colorizer colorizer, Point parentLocation, Image programImage) {
        super(parentLocation, programImage,
                "Elemente der ausgewählten Zeile aus der Logdatei " + logFileName, DIALOG_DIMENSION,
                colorizer);
        this.entries = entries;
        this.entryIndex = entryIndex;

        dateSelection = new StringSelection("Datum");
        timeSelection = new StringSelection("Zeit");
        classSelection = new StringSelection("Klasse");
        methodSelection = new StringSelection("Methode");
        lineNumberSelection = new StringSelection("Zeilennummer");
        messageSelection = new LongStringSelection("Nachricht");

        initSelections();

        addEscapeBehaviour();
        fillDialog();
    }

    private void initSelections() {
        setHeightForOptionSelections();
        setSelectionsNotEditable();
        colorizeSelections();
        fillValuesIntoSelections();
    }

    private void setHeightForOptionSelections() {
        dateSelection.setTextFieldPreferredSize(IGNORE_WIDTH_DIMENSION);
        timeSelection.setTextFieldPreferredSize(IGNORE_WIDTH_DIMENSION);
        classSelection.setTextFieldPreferredSize(IGNORE_WIDTH_DIMENSION);
        methodSelection.setTextFieldPreferredSize(IGNORE_WIDTH_DIMENSION);
        lineNumberSelection.setTextFieldPreferredSize(IGNORE_WIDTH_DIMENSION);
        //messageSelection.setPreferredSize(IGNORE_WIDTH_DIMENSION);
        // Die Nachricht nicht, die soll ja groß werden.
    }

    private void setSelectionsNotEditable() {
        dateSelection.setEditable(false);
        timeSelection.setEditable(false);
        classSelection.setEditable(false);
        methodSelection.setEditable(false);
        lineNumberSelection.setEditable(false);
        messageSelection.setEditable(false);
    }

    private void colorizeSelections() {
        Colorizer colorizer = getColorizer();
        if (null != colorizer) {
            dateSelection.colorize(colorizer);
            timeSelection.colorize(colorizer);
            classSelection.colorize(colorizer);
            methodSelection.colorize(colorizer);
            lineNumberSelection.colorize(colorizer);
            messageSelection.colorize(colorizer);
        }
    }

    private void fillValuesIntoSelections() {
        LogEntry rowElement = entries.get(entryIndex);
        dateSelection.setText(rowElement.getDate());
        timeSelection.setText(rowElement.getTime());
        classSelection.setText(rowElement.getClassName());
        methodSelection.setText(rowElement.getMethod());
        lineNumberSelection.setText(rowElement.getLineNumber());
        messageSelection.setText(rowElement.getMessage());
    }

    @Override
    protected void populateDialog() {
        add(createMainPanel(), BorderLayout.CENTER);
        add(createNavigation(), BorderLayout.SOUTH);
    }

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

        panel.add(createNormalStringSelections(), BorderLayout.NORTH);
        panel.add(messageSelection.getPanel(), BorderLayout.CENTER);

        return panel;
    }

    private Component createNormalStringSelections() {
        JPanel panel = new JPanel();
        panel.setLayout(new VerticalLayout(3, VerticalLayout.BOTH));

        panel.add(dateSelection.getPanel());
        panel.add(timeSelection.getPanel());
        panel.add(classSelection.getPanel());
        panel.add(methodSelection.getPanel());
        panel.add(lineNumberSelection.getPanel());

        return panel;
    }

    /** Erstellt die Schalter zum Vor- und Zurückschalten. */
    private Component createNavigation() {
        NavigatorPanel navigator = new NavigatorPanel(new Dimension(30, 30));

        navigator.fillNavigator();
        navigator.addFirstActionListener(e -> first());
        navigator.addPreviousActionListener(e -> previous());
        navigator.addNextActionListener(e -> next());
        navigator.addLastActionListener(e -> last());

        return navigator.centerHorizontal();
    }

    // TODO Anzeigen, welche Zeilennummer und wieviele es hat...
    private void first() {
        entryIndex = 0;
        renewValues();
    }

    private void previous() {
        if (entryIndex > 0) {
            --entryIndex;
        }
        renewValues();
    }

    private void next() {
        if (entryIndex < entries.size() - 1) {
            ++entryIndex;
        }
        renewValues();
    }

    private void last() {
        entryIndex = entries.size() - 1;
        renewValues();
    }

    private void renewValues() {
        fillValuesIntoSelections();
        refresh();
    }

}
