<?php

namespace Alma\Vendor\Alma\Client\Domain\Entity;

use Alma\Vendor\Alma\Client\Domain\ValueObject\PaymentMethod;
use Alma\Vendor\Alma\Plugin\Infrastructure\Adapter\FeePlanInterface;
use Alma\Vendor\Alma\Plugin\Infrastructure\Adapter\FeePlanListInterface;
use ArrayObject;
use OutOfBoundsException;

class FeePlanList extends ArrayObject implements FeePlanListInterface
{
    public function __construct($array = [], int $flags = 0, string $iteratorClass = "ArrayIterator")
    {
        parent::__construct(
            array_filter($array, function ($item) {
                return $item instanceof FeePlanInterface;
            }),
            $flags,
            $iteratorClass
        );
    }

    /**
     * Add a FeePlan to the FeePlanList.
     *
     * @param FeePlanInterface $feePlan
     * @return void
     */
    public function add(FeePlanInterface $feePlan): void
    {
        $this[] = $feePlan;
    }

    /**
     * Add a list of FeePlans to the FeePlanList.
     *
     * @param FeePlanListInterface $feePlanList
     * @return void
     */
    public function addList(FeePlanListInterface $feePlanList): void
    {
        foreach ($feePlanList as $feePlan) {
            $this->add($feePlan);
        }
    }

    /**
     * Returns a FeePlan by its plan key.
     * @param string $planKey
     * @return FeePlanInterface
     * @throws OutOfBoundsException if the plan key does not exist in the list.
     */
    public function getByPlanKey(string $planKey): FeePlanInterface
    {
        $filter = array_values(array_filter($this->getArrayCopy(), function ($feePlan) use ($planKey) {
            return $feePlan->getPlanKey() === $planKey;
        }));
        return $filter[0];
    }

    /**
     * Returns a list of Fee Plans that are only available for the given payment method.
     * @param array $paymentMethod
     * @return FeePlanListInterface
     */
    public function filterFeePlanList(array $paymentMethod): FeePlanListInterface
    {
        $feePlanList = new FeePlanList();
        if (in_array(PaymentMethod::CREDIT, $paymentMethod)) {
            $feePlanList->addList(new FeePlanList(array_values(array_filter($this->getArrayCopy(), function (FeePlan $feePlan) {
                return $feePlan->isCredit();
            }))));
        }
        if (in_array(PaymentMethod::PNX, $paymentMethod)) {
            $feePlanList->addList(new FeePlanList(array_values(array_filter($this->getArrayCopy(), function (FeePlan $feePlan) {
                return $feePlan->isPnXOnly();
            }))));
        }
        if (in_array(PaymentMethod::PAY_LATER, $paymentMethod)) {
            $feePlanList->addList(new FeePlanList(array_values(array_filter($this->getArrayCopy(), function (FeePlan $feePlan) {
                return $feePlan->isPayLaterOnly();
            }))));
        }
        if (in_array(PaymentMethod::PAY_NOW, $paymentMethod)) {
            $feePlanList->addList(new FeePlanList(array_values(array_filter($this->getArrayCopy(), function (FeePlan $feePlan) {
                return $feePlan->isPayNow();
            }))));
        }

        return $feePlanList;
    }


    /**
     * Returns a list of Fee Plans that are only allowed.
     *
     * @return FeePlanListInterface
     */
    public function filterAllowed(): FeePlanListInterface
    {
        return new FeePlanList(
            array_values(
                array_filter($this->getArrayCopy(), function(FeePlan $feePlan) {
                    return $feePlan->isAllowed();
                })
            )
        );
    }
}
