package com.braintreeocc.controllers;

import com.braintree.exceptions.InvalidPaymentInfoException;
import de.hybris.platform.commercefacades.order.CartFacade;
import de.hybris.platform.commercefacades.order.CheckoutFacade;
import de.hybris.platform.commercefacades.order.data.CartData;
import de.hybris.platform.commercefacades.user.UserFacade;
import de.hybris.platform.commercefacades.user.data.AddressData;
import de.hybris.platform.commercewebservicescommons.errors.exceptions.CartAddressException;
import de.hybris.platform.webservicescommons.validators.EnumValueValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import javax.annotation.Resource;

public class BraintreeBaseCommerceController extends BraintreeBaseController {

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

    @Resource(name = "userFacade")
    private UserFacade userFacade;

    @Resource(name = "checkoutFacade")
    private CheckoutFacade checkoutFacade;

    @Resource(name = "commerceWebServicesCartFacade2")
    private CartFacade cartFacade;

    @Resource(name = "addressDTOValidator")
    private Validator addressDTOValidator;

    @Resource(name = "deliveryAddressValidator")
    private Validator deliveryAddressValidator;

    @Resource(name = "orderStatusValueValidator")
    private EnumValueValidator orderStatusValueValidator;

    protected AddressData createAddressInternal(final AddressData addressData) {
        addressData.setShippingAddress(true);
        addressData.setVisibleInAddressBook(true);
        userFacade.addAddress(addressData);
        if (addressData.isDefaultAddress()) {
            userFacade.setDefaultAddress(addressData);
        }
        return addressData;
    }

    protected CartData setCartDeliveryAddressInternal(final String addressId) {
        LOG.debug("setCartDeliveryAddressInternal: {}", logParam("addressId", addressId));
        final AddressData address = new AddressData();
        address.setId(addressId);
        final Errors errors = new BeanPropertyBindingResult(address, "addressData");
        deliveryAddressValidator.validate(address, errors);
        if (errors.hasErrors()) {
            throw new CartAddressException("Address given by id " + sanitize(addressId) + " is not valid",
                    CartAddressException.NOT_VALID, addressId);
        }
        if (checkoutFacade.setDeliveryAddress(address)) {
            return getSessionCart();
        }
        throw new CartAddressException(
                "Address given by id " + sanitize(addressId) + " cannot be set as delivery address in this cart",
                CartAddressException.CANNOT_SET, addressId);
    }

    protected CartData setPaymentDetailsInternal(final String paymentDetailsId) throws InvalidPaymentInfoException {
        LOG.debug("setPaymentDetailsInternal: {}", logParam("paymentDetailsId", paymentDetailsId));
        if (checkoutFacade.setPaymentDetails(paymentDetailsId)) {
            return getSessionCart();
        }
        throw new InvalidPaymentInfoException(paymentDetailsId);
    }

    protected void validateStatusesEnumValue(final String statuses) {
        if (statuses == null) {
            return;
        }

        final String[] statusesStrings = statuses.split(BraintreeoccControllerConstants.ENUM_VALUES_SEPARATOR);
        validate(statusesStrings, "", orderStatusValueValidator);
    }

    protected CartData getSessionCart() {
        return cartFacade.getSessionCart();
    }

    protected CheckoutFacade getCheckoutFacade() {
        return checkoutFacade;
    }

    protected Validator getAddressDTOValidator() {
        return addressDTOValidator;
    }
}
