<?php
/**
 * 2018 Paysera
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * @author Paysera <plugins@paysera.com>
 * @copyright 2018 Paysera
 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of Paysera
 */
declare(strict_types=1);

namespace Paysera\Delivery;

use Paysera\Delivery\Helper\TabHelper;

if (!defined('_PS_VERSION_')) {
    exit;
}

class PayseraDeliveryConfiguration
{
    public const PROJECT_ID = 'PAYSERA_DELIVERY_PROJECT_ID';
    public const RESOLVED_PROJECT_ID = 'PAYSERA_DELIVERY_RESOLVED_PROJECT_ID';
    public const PROJECT_PASSWORD = 'PAYSERA_DELIVERY_PROJECT_PASSWORD';
    public const TEST_MODE = 'PAYSERA_DELIVERY_TEST_MODE';
    public const DELIVERY_GATEWAY_LIST = 'PAYSERA_DELIVERY_GATEWAY_LIST';
    public const DELIVERY_CARRIER_LIST = 'PAYSERA_DELIVERY_CARRIER_LIST';
    public const BALTIC_STATES = 'Baltic States';
    public const DELIVERY_COUNTRIES = ['LT', 'LV', 'EE'];
    public const TYPE_RECEIVER = 'receiver';
    public const TYPE_COURIER = 'courier';
    public const TYPE_PARCEL_MACHINE = 'parcel-machine';
    public const TYPE_TERMINALS = 'terminals';
    public const DEFAULT_MAX_WEIGHT = 10;
    /**
     * @var TabHelper
     */
    private $tabHelper;

    public function __construct()
    {
        $this->tabHelper = new TabHelper();
    }

    public function getProjectId(): ?string
    {
        $projectId = \Configuration::get(self::PROJECT_ID);

        return $projectId !== false && $projectId !== '' ? $projectId : null;
    }

    /**
     * @param string $resolvedProjectId
     * @return bool
     */
    public function setResolvedProjectId(string $resolvedProjectId): bool
    {
        return (bool)\Configuration::updateValue(self::RESOLVED_PROJECT_ID, $resolvedProjectId);
    }

    /**
     * @return string|null
     */
    public function getResolvedProjectId(): ?string
    {
        $resolvedProjectId = \Configuration::get(self::RESOLVED_PROJECT_ID);

        return $resolvedProjectId !== false && $resolvedProjectId !== '' ? $resolvedProjectId : null;
    }

    public function getProjectPassword(): ?string
    {
        $projectPassword = \Configuration::get(self::PROJECT_PASSWORD);

        return $projectPassword !== false && $projectPassword !== '' ? $projectPassword : null;
    }

    public function isTestModeEnabled(): bool
    {
        return (bool) \Configuration::get(self::TEST_MODE);
    }

    /**
     * @return array<int, array<string, int|string|array<int, mixed>>>
     */
    public function getDeliveryGateways(): array
    {
        $gatewayList = \Configuration::get(self::DELIVERY_GATEWAY_LIST);
        $result = $gatewayList !== false ? json_decode($gatewayList, true) : null;

        return is_array($result) ? $result : [];
    }

    /**
     * @return array<int, array<string, int|string>>
     */
    public function getDeliveryCarriers(): array
    {
        $carrierList = \Configuration::get(self::DELIVERY_CARRIER_LIST);
        $result = $carrierList !== false ? json_decode($carrierList, true) : null;

        return is_array($result) ? $result : [];
    }

    public function setProjectId(string $value = ''): bool
    {
        return (bool) \Configuration::updateValue(self::PROJECT_ID, $value);
    }

    public function setProjectPassword(string $value = ''): bool
    {
        return (bool) \Configuration::updateValue(self::PROJECT_PASSWORD, $value);
    }

    public function setTestMode(bool $value = false): bool
    {
        return (bool) \Configuration::updateValue(self::TEST_MODE, $value);
    }

    /**
     * @param array<int|string, array<string, mixed>> $deliveryGateways
     *
     * @return bool
     */
    public function setDeliveryGateways(array $deliveryGateways = []): bool
    {
        uasort($deliveryGateways, function ($gatewayA, $gatewayB) {
            return (int) ($gatewayB['enabled'] - $gatewayA['enabled']) ?: $gatewayA['description'] <=> $gatewayB['description'];
        });

        return (bool) \Configuration::updateValue(self::DELIVERY_GATEWAY_LIST, json_encode($deliveryGateways));
    }

    /**
     * @param array<int, array<string, mixed>> $daliveryCarriers
     *
     * @return bool
     */
    public function setDeliveryCarriers(array $daliveryCarriers = []): bool
    {
        return (bool) \Configuration::updateValue(self::DELIVERY_CARRIER_LIST, json_encode($daliveryCarriers));
    }

    public function install(): void
    {
        $this->setProjectId();
        $this->setProjectPassword();
        $this->setDeliveryGateways();
        $this->setDeliveryCarriers();
        $this->setTestMode();
        $this->tabHelper->installTabs();
    }

    public function disable(): void
    {
        foreach ($this->getDeliveryCarriers() as $carrier) {
            $carrierObject = new \Carrier((int) $carrier['carrier_id']);
            $carrierObject->active = false;
            $carrierObject->update();
        }
    }

    public function enable(): void
    {
        foreach ($this->getDeliveryCarriers() as $carrier) {
            $carrierObject = new \Carrier((int) $carrier['carrier_id']);
            $carrierObject->active = true;
            $carrierObject->update();
        }
    }

    public function uninstall(): void
    {
        foreach ($this->getDeliveryCarriers() as $carrier) {
            (new \Carrier((int) $carrier['carrier_id']))->delete();
        }

        \Configuration::deleteByName(self::PROJECT_ID);
        \Configuration::deleteByName(self::PROJECT_PASSWORD);
        \Configuration::deleteByName(self::TEST_MODE);
        \Configuration::deleteByName(self::RESOLVED_PROJECT_ID);
        \Configuration::deleteByName(self::DELIVERY_GATEWAY_LIST);
        \Configuration::deleteByName(self::DELIVERY_CARRIER_LIST);

        $this->tabHelper->uninstallTabs();
    }
}
