<?php

namespace LivraisonParSecteurs;

use DateInterval;
use LivraisonParSecteurs\Model\LpsAreaCityQuery;
use LivraisonParSecteurs\Model\LpsAreaQuery;
use Propel\Runtime\Connection\ConnectionInterface;
use Propel\Runtime\Propel;
use Thelia\Core\Translation\Translator;
use Thelia\Install\Database;
use Thelia\Model\AddressQuery;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Country;
use Thelia\Model\OrderPostage;
use Thelia\Module\AbstractDeliveryModule;
use Thelia\Module\Exception\DeliveryException;


class LivraisonParSecteurs extends AbstractDeliveryModule
{
    /** @var string */
    const DOMAIN_NAME = 'livraisonparsecteurs';
    const MESSAGE_DOMAIN = 'livraisonparsecteurs';
    const VARIABLE_MINIMUM_DELAY = 'minimum_delay_before_order';
    const LPS_AREA_SCHEDULE_ID = 'lps_area_schedule_id';
    const LPS_CHOSEN_ADDRESS = 'lps_chosen_delivery_address';
    const LPS_DELIVERY_DATE = 'lps_delivery_date';
    const LPS_DELIVERY_BEGIN_TIME = 'lps_begin_time';
    const LPS_DELIVERY_END_TIME = 'lps_end_time';
    const FORMAT_DATES = 'd/m/Y';
    const FORMAT_HEURES = 'H:i';
    const FORMAT_DATE_COMPLETE = 'Y-m-d H:i:s';
    const SECTEUR_ACTIF = 1;


    /**
     * @param ConnectionInterface|null $con
     */
    public function postActivation(ConnectionInterface $con = null)
    {
        $database = new Database($con->getWrappedConnection());
        $database->insertSql(null, array(__DIR__ . '/Config/thelia.sql'));
        $database->insertSql(null, array(__DIR__ . '/Config/insert.sql'));
    }

    /**
     * This method is called by the Delivery  loop, to check if the current module has to be displayed to the customer.
     * Override it to implements your delivery rules/
     *
     * If you return true, the delivery method will de displayed to the customer
     * If you return false, the delivery method will not be displayed
     *
     * @param Country $country the country to deliver to.
     *
     * @return boolean
     */
    public function isValidDelivery(Country $country)
    {
        $isValid = false;
        $con = Propel::getConnection();

        $currentAddressId = $this->getRequest()->getSession()->getOrder()->getChoosenDeliveryAddress();
        if (!empty($currentAddressId)) {
            $zipcode = AddressQuery::create()->filterById($currentAddressId)->findOne($con)->getZipcode();

            // Condition 1 : le client doit être situé dans un secteur couvert par la livraison à domicile.
            if (null !== $areaId = LpsAreaCityQuery::create()->filterByZipcode($zipcode)->findOne($con))
            {
                $area = LpsAreaQuery::create()->findOneById($areaId);

                // Condition 2 : le secteur doit être actif à date.
                if ($area->getActive() === self::SECTEUR_ACTIF)
                {
                    // Condition 3 : le panier doit avoir atteint le minimum de commande pour ce secteur.
                    $montantPanier = $this->getRequest()->getSession()->getSessionCart($this->getDispatcher())->getTaxedAmount($country);
                    $montantMinimum = $area->getMinimumAmount();

                    if ($montantPanier >= $montantMinimum)
                        $isValid = true;
                }
            }
        }
        return $isValid;
    }


    /**
     * Calculate and return delivery price in the shop's default currency
     *
     * @param Country $country the country to deliver to.
     *
     * @return OrderPostage|float             the delivery price
     * @throws DeliveryException if the postage price cannot be calculated.
     */
    public function getPostage(Country $country)
    {
        if (! $this->isValidDelivery($country)) {
            throw new DeliveryException(
                Translator::getInstance()->trans("This module cannot be used on the current cart.")
            );
        }

        $price = 0;
        $con = Propel::getConnection();
        $currentAddressId = $this->getRequest()->getSession()->getOrder()->getChoosenDeliveryAddress();
        if (!empty($currentAddressId)) {
            $zipcode = AddressQuery::create()->filterById($currentAddressId)->findOne($con)->getZipcode();
            $areaId = LpsAreaCityQuery::create()->findOneByZipcode($zipcode)->getIdArea();
            $price = LpsAreaQuery::create()->findOneById($areaId)->getPrice();
        }

        return $price;
    }

    static public function getDayLabel($int)
    {
        $translator = Translator::getInstance();

        $days = [
            $translator->trans("Monday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Tuesday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Wednesday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Thursday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Friday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Saturday", [], LivraisonParSecteurs::MESSAGE_DOMAIN),
            $translator->trans("Sunday", [], LivraisonParSecteurs::MESSAGE_DOMAIN)
        ];

        if ($int === null)
            return $days;
        else
            return $days[$int];
    }

    static public function calculateRelativeDate($baseDay)
    {
        $minimumDelayBeforeOrder = ConfigQuery::read(LivraisonParSecteurs::VARIABLE_MINIMUM_DELAY);
        $date = new \DateTime();
        $date->add(new DateInterval('P'. $minimumDelayBeforeOrder . 'D'));

        $nextPossibleDay = '';
        switch ($baseDay) {
            case 0 :
                $nextPossibleDay = $date->modify('next monday');
                break;
            case 1 :
                $nextPossibleDay = $date->modify('next tuesday');
                break;
            case 2 :
                $nextPossibleDay = $date->modify('next wednesday');
                break;
            case 3 :
                $nextPossibleDay = $date->modify('next thursday');
                break;
            case 4 :
                $nextPossibleDay = $date->modify('next friday');
                break;
            case 5 :
                $nextPossibleDay = $date->modify('next saturday');
                break;
            case 6 :
                $nextPossibleDay = $date->modify('next sunday');
                break;
        }

        return $nextPossibleDay;
    }
}
