package com.ease.gsms.android.plugins;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.apache.cordova.CordovaInterface;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class PartCountingBroadcastReceiver extends BroadcastReceiver {

    final int partCount;

    final UUID messageUUID;

    final AtomicInteger partCountdown;

    final CordovaInterface cordova;

    final Map<Integer, Integer> resultCodeStats;

    protected PartCountingBroadcastReceiver(CordovaInterface cordova, int partCount, UUID messageUUID) {
        this.cordova = cordova;
        this.partCount = partCount;
        this.messageUUID = messageUUID;
        partCountdown = new AtomicInteger(partCount);
        resultCodeStats = new HashMap<>();
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        int resultCode = actOnResultCode(intent);

        synchronized (resultCodeStats) {

            Integer existing = resultCodeStats.get(resultCode);

            resultCodeStats.put(
                    resultCode,
                    existing != null ? existing + 1 : 1
            );

        }

        if (partCountdown.decrementAndGet() <= 0) {

            unregisterAndComplete();

        }

    }

    AtomicBoolean alreadyUnregistered = new AtomicBoolean(false);

    void unregisterAndComplete() {

        if (alreadyUnregistered.compareAndSet(false, true)) {

            cordova.getActivity().unregisterReceiver(this);

            onComplete();

        }

    }

    protected abstract int actOnResultCode(Intent intent);

    public JSONObject getResultCodeJson() {

        try {

            JSONObject object = new JSONObject();

            object.put("messageUUID", messageUUID.toString());

            JSONObject resultCodes = new JSONObject();

            for (Map.Entry<Integer, Integer> entry : resultCodeStats.entrySet()) {
                resultCodes.put("" + entry.getKey(), entry.getValue());
            }

            object.put("resultCodes", resultCodes);

            return object;

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

    abstract void onComplete();

}
