/**
 * Copyright © 2012-2023 by Data Virtuality GmbH
 */
package org.teiid.jboss.coordination;

import java.util.LinkedList;
import java.util.List;

/**
 * @author Allan Vital
 * @date 2023.06.05
 */
public class CoordinatorLatch {

    private String nodeName = "";
    private String coordinator = "";
    private String prevCoordinator = "";
    private final List<CoordinatorChangeEventListener> listeners = new LinkedList<>();
    private final Object LOCK = new Object();

    private static CoordinatorLatch INSTANCE;

    public static CoordinatorLatch getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new CoordinatorLatch();
        }
        return INSTANCE;
    }

    private CoordinatorLatch() { }

    public void init(String nodeName, String coordinator) {
        this.nodeName = nodeName;
        this.coordinator = coordinator;
    }

    public void setCoordinator(String coordinator) {
        synchronized (LOCK) {
            String currentCoordinator = this.coordinator;
            this.coordinator = coordinator;
            if (!currentCoordinator.equals(coordinator)) {
                this.prevCoordinator = currentCoordinator;
                notifyCoordinatorChange(currentCoordinator, coordinator);
            }
        }
    }

    public boolean isCoordinatorNode() {
        synchronized (LOCK) {
            return this.coordinator.equalsIgnoreCase(this.nodeName);
        }
    }

    private void notifyCoordinatorChange(String oldCoordinator, String newCoordinator) {
        for (CoordinatorChangeEventListener listener : listeners) {
            listener.onCoordinatorChange(oldCoordinator, newCoordinator, this.isCoordinatorNode());
        }
    }

    public void addListener(CoordinatorChangeEventListener listener) {
        this.listeners.add(listener);
    }

    public void removeListener(CoordinatorChangeEventListener listener) {
        this.listeners.remove(listener);
    }

    public void reset() {
        this.coordinator = "";
        this.nodeName = "";
        this.prevCoordinator = "";
        this.listeners.clear();
    }

    public String getNodeName() {
        return this.nodeName;
    }

    public String getPrevCoordinator() {
        return prevCoordinator;
    }
}