package de.visone.nlpext.deprecated;

import java.util.HashMap;
import java.util.Map;

import de.visone.analysis.gui.tab.CentralityControl;
import de.visone.analysis.gui.tab.IndicesCard.EdgeCentralityCard;
import de.visone.analysis.gui.tab.IndicesCard.NodeCentralityCard;
import de.visone.base.Mediator;
import de.visone.base.Network;
import de.visone.collections.SingleNetworkSet;
import de.visone.gui.tabs.AbstractAlgorithmCard;
import de.visone.gui.tabs.AbstractTabCard;
import de.visone.gui.tabs.TopLevelTabComponent;

/**
 * Utility class for computing centralities. Not thread safe.
 * 
 * @author matthias
 */
public class CentralityUtil {
    private static final Map<String, CentralityControl<?>> nodeCentralities = new HashMap<String, CentralityControl<?>>();
    private static final Map<String, CentralityControl<?>> edgeCentralities = new HashMap<String, CentralityControl<?>>();
    private static final TopLevelTabComponent DUMMY_TAB_COMPONENT = new TopLevelTabComponent() {
        @Override
        public void setAlgorithm(final AbstractAlgorithmCard card) {
        }

        @Override
        public void runnabilityStatusChanged() {
        }
    };

    private CentralityUtil() {
    }

    public static Centrality getNodeCentrality(final String algorithmName,
            final String edgeLengthAttribute, final String edgeStrengthAttribute) {
        if (nodeCentralities.isEmpty())
            fillNodeCentralities();
        if (!nodeCentralities.containsKey(algorithmName))
            return null;

        final CentralityControl<?> algo = nodeCentralities.get(algorithmName);
        algo.getParameterPanel();
        return new Centrality(algo, edgeLengthAttribute, edgeStrengthAttribute);
    }

    public static Centrality getEdgeCentrality(final String algorithmName,
            final String edgeLengthAttribute, final String edgeStrengthAttribute) {
        if (edgeCentralities.isEmpty())
            fillEdgeCentralities();
        if (!edgeCentralities.containsKey(algorithmName))
            return null;

        final CentralityControl<?> algo = edgeCentralities.get(algorithmName);
        algo.getParameterPanel();
        return new Centrality(algo, edgeLengthAttribute, edgeStrengthAttribute);
    }

    private static void fillNodeCentralities() {
        nodeCentralities.putAll(new NodeCentralityCard(Mediator.getInstance()) {
            private Map<String, CentralityControl<?>> getAlgorithms() {
                setTabComponent(DUMMY_TAB_COMPONENT);
                final Map<String, CentralityControl<?>> algorithms = new HashMap<String, CentralityControl<?>>();
                for (final AbstractTabCard card : childCards)
                    if (card instanceof CentralityControl)
                        algorithms.put(card.getCardName(),
                                (CentralityControl<?>) card);
                return algorithms;
            }
        }.getAlgorithms());
    }

    private static void fillEdgeCentralities() {
        edgeCentralities.putAll(new EdgeCentralityCard(Mediator.getInstance()) {
            private Map<String, CentralityControl<?>> getAlgorithms() {
                setTabComponent(DUMMY_TAB_COMPONENT);
                final Map<String, CentralityControl<?>> algorithms = new HashMap<String, CentralityControl<?>>();
                for (final AbstractTabCard card : childCards)
                    if (card instanceof CentralityControl)
                        algorithms.put(card.getCardName(),
                                (CentralityControl<?>) card);
                return algorithms;
            }
        }.getAlgorithms());
    }

    /**
     * A centrality algorithm, wrapped for extensions. Not thread safe.
     * 
     * @author matthias
     */
    public static final class Centrality {
        private final CentralityControl<?> algo;
        private final String edgeLength;
        private final String edgeStrength;

        private Centrality(final CentralityControl<?> algo,
                final String edgeLength, final String edgeStrength) {
            this.algo = algo;
            this.edgeLength = edgeLength;
            this.edgeStrength = edgeStrength;
        }

        public void runAlgorithm(final String resultAttributeName,
                final Network network) {
            algo.setActiveNetworkSet(new SingleNetworkSet(network));
            algo.setEdgeLength(edgeLength);
            algo.setEdgeStrength(edgeStrength);
            algo.setStandardizeEnabled(true);
            algo.setTargetAttributeName(resultAttributeName);
            algo.setParameters(network);
            algo.prepare(network);
            algo.runAlgorithm(network);
            algo.cleanup(network);
        }
    }
}
