<?php

namespace CouponsPlus\App\Coupon\Attributes\Data;

use Error;
use Exception;
use CouponsPlus\app\coupon\attributes\abilities\AttributeData;
use CouponsPlus\Original\Characters\StringManager;
use CouponsPlus\Original\Collections\Collection;
use WC_Product_Attribute;
use CouponsPlus\App\Coupon\Attributes\Abilities\WithSelectedValues;
use CouponsPlus\App\Coupon\Attributes\Factories\GlobalAttributeValueDataFactory;

class GlobalAttributeData implements AttributeData, WithSelectedValues
{
    /**
     * @var WC_Product_Attribute|array
     */
    protected $data;
    /**
     * @var GlobalAttributeValueDataFactory
     */
    protected $attributeValueFactory;
    protected $selectedValues;
    /**
     * @var StringManager
     */
    protected $rawKey;

    public function __construct(WC_Product_Attribute $data, GlobalAttributeValueDataFactory $attributeValueFactory)
    {
        $this->data = $data;
        $this->attributeValueFactory = $attributeValueFactory;
        $this->attributeValueFactory->setAttributeData($this);
        $this->rawKey = new StringManager(wc_attribute_taxonomy_name_by_id($this->data->get_id()));
    }

    /**
     * When called, these values will be used instead of the ones from the database
     * Useful for when you want to have an instance with selected values
     *
     * @param array $values Any valid attribute data values that can be accepted by the GlobalAttributeValueDataFactory
     */
    public function useValues(array $values)
    {
        $this->selectedValues = $values;
    }

    public function getKey(): StringManager
    {
        return $this->rawKey->startsWith('pa_') ? $this->rawKey->replace('pa_', '') : $this->rawKey;
    }

    public function getId()
    {
        return $this->data->get_id();
    }

    /**
     * @return Collection of WP_Term
     */
    public function getValues(): Collection
    {
        return Collection::create($this->getValuesToUse())->map(function ($value) {
            try {
                return $this->attributeValueFactory->create($value);
            } catch (\Error $e) {
                return null;
            }
        })->filter(function ($value) {
            return $value !== null;
        });
    }

    /**
     * @return array
     */
    protected function getValuesToUse(): array
    {
        if ($this->selectedValues) {
            return $this->selectedValues;
        }

        return $this->data->get_options();
    }
}