package com.gingersoft.gsa.cloud.common.printer.plugins;

import android.graphics.Bitmap;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.annotations.NonNull;
import io.reactivex.annotations.Nullable;
import io.reactivex.functions.Consumer;

/**
 * @作者: bin
 * @創建時間: 2021-01-25 9:46
 * @更新時間: 2021-01-25 9:46
 * @描述:
 */
public class PrinterFlowProxy {

    private static volatile PrinterFlowProxy sPrinterPlugins = null;

    private ArrayList<PrinterFlowListener> mPrinterFlowListeners = new ArrayList<>();

    @Nullable
    private Consumer<? super Throwable> errorHandler;

    private PrinterFlowProxy() {
    }

    public static PrinterFlowProxy newInstance() {
        if (sPrinterPlugins == null) {
            synchronized (PrinterFlowProxy.class) {
                if (sPrinterPlugins == null) {
                    sPrinterPlugins = new PrinterFlowProxy();
                }
            }
        }
        return sPrinterPlugins;
    }

    public void onError(@NonNull Throwable error) {
        Consumer<? super Throwable> f = errorHandler;
        if (error == null) {
            error = new NullPointerException("onError called with null");
        }
        if (f != null) {
            try {
                f.accept(error);
                return;
            } catch (Throwable e) {
                e.printStackTrace();
                uncaught(e);
            }
        }
        error.printStackTrace();
        uncaught(error);
    }

    void uncaught(@NonNull Throwable error) {
        Thread currentThread = Thread.currentThread();
        Thread.UncaughtExceptionHandler handler = currentThread.getUncaughtExceptionHandler();
        handler.uncaughtException(currentThread, error);
    }

    public void setErrorHandler(Consumer<? super Throwable> errorHandler) {
        this.errorHandler = errorHandler;
    }

    public void registerPrinterFlowListener(PrinterFlowListener listener) {
        mPrinterFlowListeners.add(listener);
    }

    public void unregisterPrinterFlowListener(PrinterFlowListener listener) {
        mPrinterFlowListeners.remove(listener);
    }

    public void dispatchPrinterDataBefore(int orderType, int printType, String printerData, String printerDeviceInfo) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).onPrinterDataBefore(orderType, printType, printerData, printerDeviceInfo);
            }
        }
    }

    public void dispatchPrinterBitmapBefore(int orderType, int printType, String directoryName, List<Bitmap> bitmaps) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).onPrinterBitmapBefore(orderType, printType, directoryName, bitmaps);
            }
        }
    }

    public void dispatchPrintSuccess() {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).onPrintSuccess();
            }
        }
    }

    public void dispatchPrintError(Exception e, int errorCode) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).onPrintError(e, errorCode);
            }
        }
    }

    public void dispatchConnectionBefore(String deviceName, String IP, int port, long ioTimeout, long printTimeout) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).connectionBefore(deviceName, IP, port, ioTimeout, printTimeout);
            }
        }
    }

    public void dispatchConnectionSuccess() {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).connectionSuccess();
            }
        }
    }

    public void dispatchConnectionError(Exception e) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).connectionError(e);
            }
        }
    }

    public void dispatchDisconnect(Exception e) {
        Object[] listeners = collectPrinterFlowListener();
        if (listeners != null) {
            for (int i = 0; i < listeners.length; i++) {
                ((PrinterFlowListener) listeners[i]).disconnect(e);
            }
        }
    }

    private Object[] collectPrinterFlowListener() {
        Object[] listeners = null;
        synchronized (mPrinterFlowListeners) {
            if (mPrinterFlowListeners.size() > 0) {
                listeners = mPrinterFlowListeners.toArray();
            }
        }
        return listeners;
    }
}
