<?php

declare(strict_types=1);

namespace Gls\GlsPoland\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gls\GlsPoland\Carrier\CarrierId;
use Gls\GlsPoland\Carrier\CarrierType;
use Gls\GlsPoland\Country\IsoCode;
use Gls\GlsPoland\Repository\CarrierRepository;

/**
 * @ORM\Entity(repositoryClass=CarrierRepository::class)
 * @ORM\Table(name="gls_poland_carrier")
 * @ORM\InheritanceType(value="SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({CarrierType::COURIER=CourierCarrier::class, CarrierType::SHOP_DELIVERY=ShopDeliveryCarrier::class})
 */
abstract class Carrier
{
    /**
     * @ORM\Id()
     * @ORM\Column(name="id_reference", type="integer")
     */
    private $id;

    /**
     * @var string[]
     *
     * @ORM\Column(type="simple_array")
     */
    private $countries;

    private $isoCodes;

    public function __construct(CarrierId $id, IsoCode ...$countryIsoCodes)
    {
        if ([] === $countryIsoCodes) {
            throw new \LogicException('Carrier has to be available in at least a single country.');
        }

        $this->id = $id->getValue();
        $this->countries = array_map('strval', $countryIsoCodes);
        $this->isoCodes = $countryIsoCodes;
    }

    public function getId(): CarrierId
    {
        return CarrierId::from($this->id);
    }

    /**
     * @return IsoCode[]
     */
    public function getCountries(): array
    {
        return $this->isoCodes ?? ($this->isoCodes = array_map([IsoCode::class, 'from'], $this->countries));
    }
}
