package com.braintree.warehouse;

import de.hybris.platform.basecommerce.enums.ConsignmentStatus;
import de.hybris.platform.commerceservices.model.PickUpDeliveryModeModel;
import de.hybris.platform.core.PK;
import de.hybris.platform.core.Registry;
import de.hybris.platform.ordersplitting.model.ConsignmentEntryModel;
import de.hybris.platform.ordersplitting.model.ConsignmentModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.time.TimeService;
import de.hybris.platform.warehouse.Process2WarehouseAdapter;
import de.hybris.platform.warehouse.Warehouse2ProcessAdapter;
import de.hybris.platform.warehouse.WarehouseConsignmentStatus;
import org.apache.log4j.Logger;


public class BrainTreeMockProcess2WarehouseAdapter implements Process2WarehouseAdapter {

    private static final Logger LOG = Logger.getLogger(BrainTreeMockProcess2WarehouseAdapter.class);

    private ModelService modelService;
    private Warehouse2ProcessAdapter warehouse2ProcessAdapter;
    private TimeService timeService;

    @Override
    public void prepareConsignment(final ConsignmentModel consignment) {
        for (final ConsignmentEntryModel consignmentEntries : consignment.getConsignmentEntries()) {
            consignmentEntries.setShippedQuantity(consignmentEntries.getQuantity());
        }
        consignment.setStatus(ConsignmentStatus.READY);
        modelService.save(consignment);

        final Thread warehouse = new Thread(new Warehouse(getTenantID(), getConsignmentPkLongValue(consignment)));
        warehouse.start();

        try {
            Thread.sleep(3000);
        } catch (final InterruptedException e) {
            //nothing to do
        }
    }

    protected long getConsignmentPkLongValue(ConsignmentModel consignment) {
        return consignment.getPk()
                .getLongValue();
    }

    protected String getTenantID() {
        return Registry.getCurrentTenant().getTenantID();
    }

    public class Warehouse implements Runnable {

        private final long consignment;
        private final String tenant;

        public Warehouse(final String tenant, final long consignment) {
            super();

            this.consignment = consignment;
            this.tenant = tenant;
        }

        @Override
        public void run() {
            Registry.setCurrentTenant(Registry.getTenantByID(tenant));
            try {
                final ConsignmentModel model = modelService.get(PK.fromLong(consignment));
                warehouse2ProcessAdapter.receiveConsignmentStatus(model, WarehouseConsignmentStatus.COMPLETE);
            } finally {
                Registry.unsetCurrentTenant();
            }
        }

    }


    @Override
    public void shipConsignment(final ConsignmentModel consignment) {
        if (consignment == null) {
            LOG.warn("No consignment to ship");
        } else {
            if (consignment.getDeliveryMode() instanceof PickUpDeliveryModeModel) {
                consignment.setStatus(ConsignmentStatus.READY_FOR_PICKUP);
            } else {
                consignment.setStatus(ConsignmentStatus.SHIPPED);
            }
            consignment.setShippingDate(timeService.getCurrentTime());
            for (final ConsignmentEntryModel entry : consignment.getConsignmentEntries()) {
                entry.setShippedQuantity(entry.getOrderEntry().getQuantity());
                modelService.save(entry);
            }
            modelService.save(consignment);
            if (LOG.isInfoEnabled()) {
                LOG.info("Consignment [" + consignment.getCode() + "] shipped");
            }
        }
    }

    public void setModelService(final ModelService modelService) {
        this.modelService = modelService;
    }

    public void setWarehouse2ProcessAdapter(final Warehouse2ProcessAdapter warehouse2ProcessAdapter) {
        this.warehouse2ProcessAdapter = warehouse2ProcessAdapter;
    }

    public void setTimeService(final TimeService timeService) {
        this.timeService = timeService;
    }

}
