package com.braintree.delivery.service.impl;

import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull;

import com.braintree.delivery.dao.BraintreeCountyZoneDeliveryModeDao;
import com.braintree.delivery.service.BraintreeDeliveryService;
import de.hybris.platform.commerceservices.delivery.impl.DefaultDeliveryService;
import de.hybris.platform.core.model.c2l.CountryModel;
import de.hybris.platform.core.model.c2l.CurrencyModel;
import de.hybris.platform.core.model.order.AbstractOrderModel;
import de.hybris.platform.core.model.order.delivery.DeliveryModeModel;
import de.hybris.platform.servicelayer.i18n.daos.CountryDao;
import de.hybris.platform.util.PriceValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


public class DefaultBraintreeDeliveryService extends DefaultDeliveryService implements BraintreeDeliveryService {

    protected BraintreeCountyZoneDeliveryModeDao braintreeCountyZoneDeliveryModeDao;
    protected CountryDao countryDao;

    @Override
    public List<DeliveryModeModel> getSupportedDeliveryModeListForOrderAndCountryCode(
        AbstractOrderModel abstractOrder, String countyCode) {
        validateParameterNotNull(abstractOrder, "abstractOrder model cannot be null");
        validateParameterNotNull(countyCode, "countyCode cannot be null");
        final CurrencyModel currency = abstractOrder.getCurrency();
        List<CountryModel> countriesByCode = countryDao.findCountriesByCode(countyCode);
        CountryModel countryModel = null;
        if (countriesByCode.size() > 0) {
            countryModel = countriesByCode.get(0);
        }
        List<DeliveryModeModel> deliveryModes;
        if (countryModel != null && currency != null) {
            deliveryModes = new ArrayList<>(
                braintreeCountyZoneDeliveryModeDao.findDeliveryModes(abstractOrder, countryModel));
            sortDeliveryModes(deliveryModes, abstractOrder);
            return deliveryModes;
        }
        return Collections.emptyList();
    }

    @Override
    public PriceValue countDeliveryPriceForOrderAndCountyCode(AbstractOrderModel abstractOrder,
        String countyCode) {
        List<DeliveryModeModel> supportedDeliveryModes = getSupportedDeliveryModeListForOrderAndCountryCode(
            abstractOrder, countyCode);
        if (supportedDeliveryModes.size() == 0) {
            return null;
        }
        List<CountryModel> countriesByCode = countryDao.findCountriesByCode(countyCode);
        CountryModel countryModel;
        if (countriesByCode.size() == 0) {
            return null;
        }
        countryModel = countriesByCode.get(0);
        return supportedDeliveryModes.stream()
            .map(deliveryModeModel -> braintreeCountyZoneDeliveryModeDao
                .countPriceForDeliveryMode(deliveryModeModel, abstractOrder, countryModel))
            .min(Comparator.comparingDouble(PriceValue::getValue))
            .orElse(null);
    }

    public void setBraintreeCountyZoneDeliveryModeDao(
        BraintreeCountyZoneDeliveryModeDao braintreeCountyZoneDeliveryModeDao) {
        this.braintreeCountyZoneDeliveryModeDao = braintreeCountyZoneDeliveryModeDao;
    }

    public void setCountryDao(CountryDao countryDao) {
        this.countryDao = countryDao;
    }
}
