package de.renew.logging.gui;

import java.util.Enumeration;
import java.util.Set;
import java.util.Vector;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import de.renew.engine.common.SimulatorEventLogger;
import de.renew.windowmanagement.Workbench;


/**
 * The controller for the gui to display the simulation log messages.
 * The class LoggingFrame contains the view implementation.
 *
 * @author Sven Offermann
 */
public class LoggingController {
    private LoggingFrame _frame;
    private LoggerTableModel _currentLoggerTableModel;

    /**
     * Creates a new Logging-Frame and adds the created object to the loggingFrameControllers.
     * @param loggingFrameControllers a set of {@link LoggingController}
     * @param workbench                {@link Workbench}
     */
    public LoggingController(
        final Set<LoggingController> loggingFrameControllers, Workbench workbench)
    {
        String[] loggerNames = findSimulationLoggerNames();

        this._frame = new LoggingFrame(this, loggerNames, workbench);
        final LoggingController controller = this;
        loggingFrameControllers.add(controller); // TODO: this is an antipattern, the set should not mutated within the constructor

        if (loggerNames.length > 0) {
            changeLogger(loggerNames[0]);
        }
    }

    /**
     * rebuild tabel model when toogled to true
     * @param update boolean
     */
    public void setPermanentUpdate(boolean update) {
        if (update == true) {
            destruct();
            _currentLoggerTableModel = new LoggerTableModel(_frame.getSelectedLoggerName());

            _frame.setTableModel(_currentLoggerTableModel);
        }

        if (_currentLoggerTableModel != null) {
            _currentLoggerTableModel.setPermanentUpdate(update);
        }
    }

    /**
     * Change the view to the logger which shall be shown.
     * @param loggerName name of the logger which shall be shown.
     */
    public void changeLogger(String loggerName) {
        showLogger(loggerName);
    }

    /**
     * Iterates over all loggers and assembles them to an array.
     * @return String[] of all logger-names.
     */
    public static String[] findSimulationLoggerNames() {
        Vector<String> loggerNames = new Vector<String>();

        Enumeration<?> ls = LogManager.getCurrentLoggers();
        while (ls.hasMoreElements()) {
            Logger logger = (Logger) ls.nextElement();
            if (logger.getName().startsWith(SimulatorEventLogger.SIM_LOG_PREFIX)) {
                Enumeration<?> as = logger.getAllAppenders();
                while (as.hasMoreElements()) {
                    Object o = as.nextElement();
                    if (o instanceof GuiAppender) {
                        loggerNames.add(logger.getName());
                    }
                }
            }
        }

        return loggerNames.toArray(new String[] { });
    }

    /**
     * create table model with trace information
     * if the appender is null an empty table model
     * will be generated.
     * @param loggerName Name of the logger.
     */
    private void showLogger(String loggerName) {
        destruct();
        _currentLoggerTableModel = new LoggerTableModel(loggerName);
        _frame.setTableModel(_currentLoggerTableModel);
    }

    /**
     * Closes the visible logging frame. Afterwards, all associated logging functionality will halt.
     */
    public void closeFrame() {
        //        this.frame.setVisible(false);
        //        this.frame.dispose();
        destruct();

    }

    /**
     * Destroys the currently registered {@link LoggerTableModel} and all associated components
     * to the logging environment.
     */
    private void destruct() {
        if (_currentLoggerTableModel != null) {
            _currentLoggerTableModel.removeAll();
            _currentLoggerTableModel = null;
        }
    }
}