package de.renew.navigator.gui;

import java.util.LinkedList;
import java.util.List;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;

import de.renew.navigator.FilesystemController;
import de.renew.navigator.NavigatorExtension;
import de.renew.navigator.NavigatorGui;
import de.renew.navigator.NavigatorPlugin;
import de.renew.navigator.models.TreeElement;
import de.renew.windowmanagement.Workbench;


/**
 * @author Konstantin Simon Maria Moellers
 * @version 2015-10-14
 */
public class NavigatorGuiProxy implements NavigatorGui {
    private final FilesystemController _fileSystem;
    private final NavigatorPlugin _plugin;
    private NavigatorGuiImpl _proxy;
    private final LinkedList<NavigatorExtension> _tempExtensions;
    private Workbench _workbench;

    /**
     * Creates a new NavigatorGuiProxy.
     * @param fileSystem the {@link FilesystemController} instance that this proxy interacts with.
     * @param workbench the {@link Workbench} instance that this proxy interacts with.
     * @param plugin the {@link NavigatorPlugin} instance that this proxy interacts with.
     */
    public NavigatorGuiProxy(
        FilesystemController fileSystem, Workbench workbench, NavigatorPlugin plugin)
    {
        this._fileSystem = fileSystem;
        this._plugin = plugin;
        this._workbench = workbench;
        _tempExtensions = new LinkedList<NavigatorExtension>();
    }

    @Override
    public void openWindow() {
        ensureProxyInitialized().openWindow();
    }

    @Override
    public void closeWindow() {
        // if there is no proxy present we don't want to create a new one just for closing it's window
        if (_proxy != null) {
            ensureProxyInitialized().closeWindow();

            ensureProxyFreed();
        }
    }

    @Override
    public List<NavigatorExtension> getExtensions() {
        if (_proxy == null) {
            return _tempExtensions;
        }

        return _proxy.getExtensions();
    }

    @Override
    public void addExtension(NavigatorExtension extension) {
        if (_proxy == null) {
            _tempExtensions.add(extension);
            return;
        }

        _proxy.addExtension(extension);
    }

    @Override
    public boolean removeExtension(NavigatorExtension extension) {
        if (_proxy == null) {
            return _tempExtensions.remove(extension);
        }

        return _proxy.removeExtension(extension);
    }

    @Override
    public DefaultFileTreeCellRenderer getTreeCellRenderer() {
        return ensureProxyInitialized().getTreeCellRenderer();
    }

    @Override
    public JTree getTree() {
        return ensureProxyInitialized().getTree();
    }

    @Override
    public DefaultMutableTreeNode getRootNode() {
        return ensureProxyInitialized().getRootNode();
    }

    @Override
    public void collapseAll() {
        ensureProxyInitialized().collapseAll();
    }

    @Override
    public void expand() {
        ensureProxyInitialized().expand();
    }

    @Override
    public void removeSelectedNodes() {
        ensureProxyInitialized().removeSelectedNodes();
    }

    @Override
    public List<TreeElement> getSelectedElements() {
        return ensureProxyInitialized().getSelectedElements();
    }

    private NavigatorGuiImpl ensureProxyInitialized() {
        if (_proxy != null) {
            return _proxy;
        }

        _proxy = new NavigatorGuiImpl(_fileSystem, _workbench, _plugin);

        // Add all temporary extensions to the GUI.
        for (NavigatorExtension extension : _tempExtensions) {
            _proxy.addExtension(extension);
        }
        _tempExtensions.clear();
        return _proxy;
    }

    private void ensureProxyFreed() {
        if (_proxy == null) {
            return;
        }

        for (NavigatorExtension extension : _proxy.getExtensions()) {
            _tempExtensions.add(extension);
        }

        //        proxy.dispose();
        _proxy = null;
    }
}