package com.ease.gsms.server.services.dispatch;

import com.ease.gsms.server.model.Dispatch;
import com.ease.gsms.server.model.DispatchStatus;
import com.ease.gsms.server.model.Message;
import com.ease.gsms.server.model.MessageStatus;
import com.ease.gsms.server.services.DispatchUpdateObserver;

import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class DispatchStatusHolder {

    boolean live;

    int totalMessageCount;

    Map<MessageStatus, AtomicInteger> messagesCountsByStatus;

    transient Set<DispatchUpdateObserver> observers;

    transient Dispatch dispatch;

    public DispatchStatusHolder(Dispatch dispatch, Set<DispatchUpdateObserver> observers, boolean live) {

        this.dispatch = dispatch;

        this.live = live;

        this.observers = observers;

        messagesCountsByStatus = new ConcurrentHashMap<>();

        for (Message message : dispatch.getMessages()) {

            messagesCountsByStatus.computeIfAbsent(message.getStatus(), s -> new AtomicInteger()).incrementAndGet();

            totalMessageCount++;

        }

    }

    public Long getId() {
        return dispatch.getId();
    }

    public UUID getUUID() {
        return dispatch.getUUID();
    }

    public String getFromICCID() {
        return dispatch.getFromICCID();
    }

    public String getSubmitter() {
        return dispatch.getSubmitter();
    }

    public Date getSubmissionDate() {
        return dispatch.getSubmissionDate();
    }

    public Date getModificationDate() {
        return dispatch.getModificationDate();
    }

    public Boolean getSendToInternationalNumbers() {
        return dispatch.getSendToInternationalNumbers();
    }

    public Boolean getSendToNationalLandlines() {
        return dispatch.getSendToNationalLandlines();
    }

    public Boolean getSendToNationalMobiles() {
        return dispatch.getSendToNationalMobiles();
    }

    public Boolean getResendIdenticalSuccessfullyDeliveredMessages() {
        return dispatch.getResendIdenticalSuccessfullyDeliveredMessages();
    }

    public Boolean getResendIdenticalSuccessfullySentMessages() {
        return dispatch.getResendIdenticalSuccessfullySentMessages();
    }

    public Boolean getResendIdenticalUnsuccessfullySentMessages() {
        return dispatch.getResendIdenticalUnsuccessfullySentMessages();
    }

    public Boolean getResendUnsentMessages() {
        return dispatch.getResendUnsentMessages();
    }

    public DispatchStatus getStatus() {
        return dispatch.getStatus();
    }

    public Boolean getAskForDeliveryReport() {
        return dispatch.getAskForDeliveryReport();
    }

    public Integer getPauseBetweenMessagesSeconds() {
        return dispatch.getPauseBetweenMessagesSeconds();
    }

    public Map<MessageStatus, Integer> getMessagesCountsByStatus() {
        return messagesCountsByStatus.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get()));
    }

    public int getTotalMessageCount() {
        return totalMessageCount;
    }

    public void updateMessageStatus(MessageStatus existingStatus, MessageStatus status) {
        AtomicInteger before = messagesCountsByStatus.get(existingStatus);
        AtomicInteger after = messagesCountsByStatus.computeIfAbsent(status, s -> new AtomicInteger());
        before.decrementAndGet();
        after.incrementAndGet();
        notifyObservers();
    }

    public void notifyObservers() {
        for (DispatchUpdateObserver observer : observers) {
            observer.updated(dispatch.getSubmitter(), this);
        }
    }

}
