package it.integry.integrywmsnative.core.data_store.db.repository.datasource;

import android.os.Handler;

import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

import javax.inject.Inject;

import it.integry.integrywmsnative.core.data_store.db.dao.ArticoloOrdineDao;
import it.integry.integrywmsnative.core.data_store.db.entity.ArticoloOrdine;
import it.integry.integrywmsnative.core.data_store.db.entity.Ordine;
import it.integry.integrywmsnative.core.data_store.db.repository.ArticoliOrdineRepository;
import it.integry.integrywmsnative.core.expansion.RunnableArgs;
import it.integry.integrywmsnative.core.utility.UtilityDate;

public class ArticoliOrdineDataSource extends BaseDataSource implements ArticoliOrdineRepository {

    private final ArticoloOrdineDao mArticoloOrdineDao;

    @Inject
    public ArticoliOrdineDataSource(ExecutorService executorService,
                                    Handler handler,
                                    ArticoloOrdineDao articoloOrdineDao) {
        super(executorService, handler);
        this.mArticoloOrdineDao = articoloOrdineDao;
    }

    public void saveArticoliToOrdine(List<ArticoloOrdine> articoli, Runnable onSuccess, RunnableArgs<Exception> onError) {
        executorService.execute(() -> {
            try {
                List<ArticoloOrdine> toUpdate = new ArrayList<>();
                List<ArticoloOrdine> toInsert = new ArrayList<>();
                for (ArticoloOrdine art : articoli) {
                    if (art.getArticoloOrdineId() != null && art.getArticoloOrdineId() > 0) {
                        toUpdate.add(art);
                    } else {
                        toInsert.add(art);
                    }
                }
                for (ArticoloOrdine newArt : toInsert) {
                    mArticoloOrdineDao.insert(newArt);
                }
                mArticoloOrdineDao.updateAll(toUpdate);
                handler.post(onSuccess);

            } catch (Exception e) {
                onError.run(e);
            }
        });
    }

    public void saveArticoloToOrdine(ArticoloOrdine articolo, Runnable onSuccess, RunnableArgs<Exception> onError) {
        articolo.setDataIns(UtilityDate.getDateInstance());
        if (articolo.getArticoloOrdineId() != null && articolo.getArticoloOrdineId() > 0) {
            execute(() -> mArticoloOrdineDao.update(articolo), onSuccess, onError);
        } else {
            execute(() -> mArticoloOrdineDao.insert(articolo), onSuccess, onError);
        }
    }

    public void findArticoloByOrdineAndBarcode(Ordine ordine, String barcode, RunnableArgs<ArticoloOrdine> onSuccess, RunnableArgs<Exception> onError) {
        execute(() -> mArticoloOrdineDao.findArticoloByOrdineAndBarcode(ordine.getOrdineId(), barcode), onSuccess, onError);
    }

    public void findArticoloByScanAndOrdine(Ordine ordine, String barcode, RunnableArgs<ArticoloOrdine> onSuccess, RunnableArgs<Exception> onError) {
        executorService.execute(() -> {
            try {
                ArticoloOrdine articolo = mArticoloOrdineDao.findArticoloByCodMartAndOrdine(ordine.getOrdineId(), barcode);

                if (articolo == null) {
                    articolo = mArticoloOrdineDao.findArticoloByBarcodeAndOrdine(ordine.getOrdineId(), barcode);
                }

                if (articolo == null) {
                    String scannedCode = StringUtils.leftPad(barcode, 13, '0');
                    articolo = mArticoloOrdineDao.findArticoloByBarcodeAndOrdine(ordine.getOrdineId(), scannedCode);
                }

                final ArticoloOrdine finalArticolo = articolo;
                handler.post(() -> onSuccess.run(finalArticolo));
            } catch (Exception e) {
                onError.run(e);
            }
        });
    }

    public void findArticoliByOrdine(Ordine ordine, RunnableArgs<List<ArticoloOrdine>> onSuccess, RunnableArgs<Exception> onError) {
        execute(() -> mArticoloOrdineDao.findArticoliByOrdine(ordine.getOrdineId()), onSuccess, onError);
    }

    public void deleteArticolo(ArticoloOrdine articolo, Runnable onSuccess, RunnableArgs<Exception> onError) {
        execute(() -> mArticoloOrdineDao.delete(articolo),
                onSuccess,
                onError);
    }

}
