<?php

namespace CouponsPlus\App\Coupon\Tree\ItemSetsToDiscount;

use CouponsPlus\App\Conditions\ItemsSet;
use CouponsPlus\App\Coupon\Tree\ItemSetsToDiscount\ItemsSetToDiscount;
use CouponsPlus\Original\Collections\Collection;

class ItemsSetToDiscountCollection
{
    /**
     * @var Collection of ItemsSetToDiscount
     */
    protected Collection $itemsSetsToDiscount;

    public function __construct(?Collection $itemsSetsToDiscount = null)
    {
        $this->itemsSetsToDiscount = $itemsSetsToDiscount ?? new Collection([]);
    }

    public function addSet(ItemsSetToDiscount $itemsSetToDiscount)
    {
        $this->itemsSetsToDiscount->push($itemsSetToDiscount);
    }

    /**
     * Returns a collection of all the items in all the items sets in a single items set
     */
    public function flattenedItems(): ItemsSet
    {
        $flattenedItems = new ItemsSet([]);

        $this->itemsSetsToDiscount->forEvery(function(ItemsSetToDiscount $itemsSetToDiscount) use ($flattenedItems) : void {
            $flattenedItems->addItems($itemsSetToDiscount->itemsSet);
        });

        return $flattenedItems;
    }

    /**
     * This wil return false if one of the items sets can't be fully applied. via !$itemssettodiscount->isComplete()
     */
    public function canFullyApplyToAllSets() : bool
    {
        /** @var ItemsSetToDiscount $itemsSetToDiscount */
        foreach ($this->itemsSetsToDiscount->asArray() as $itemsSetToDiscount) {
            if (!$itemsSetToDiscount->canFillTheRequiredQuantity()) {
                return false;
            }
        }

        return true;
    }

    public function getSetsThatCannotFillRequiredQuantity() : Collection
    {
        // self explanatory right? loop and get the ones that can't be fully applied
        return $this->itemsSetsToDiscount->filter(function (ItemsSetToDiscount $itemsSetToDiscount) : bool {
            return !$itemsSetToDiscount->canFillTheRequiredQuantity();
        });
    }

    public function getSetsThatCanFillRequiredQuantity() : Collection
    {
        return $this->itemsSetsToDiscount->filter(function (ItemsSetToDiscount $itemsSetToDiscount) : bool {
            return $itemsSetToDiscount->canFillTheRequiredQuantity();
        });
    }

    public function getSetsThatCanBeAppliedPartiallyOrFully() : Collection
    {
        return $this->itemsSetsToDiscount->filter(function (ItemsSetToDiscount $itemsSetToDiscount) : bool {
            return $itemsSetToDiscount->canFillTheRequiredQuantity() || $itemsSetToDiscount->canPartiallyFillTheRequiredQuantity();
        });
    }

    public function getAll() : Collection
    {
        return $this->itemsSetsToDiscount;
    }
}