<?php

namespace Braintree\Error;

use Braintree\Util;
use Countable;
use JsonSerializable;

/**
 * Error handler
 * Handles validation errors
 *
 * Contains a read-only property $error which is a ValidationErrorCollection
 *
 * See our {@link https://developer.paypal.com/braintree/docs/reference/general/result-objects#error-results developer docs} for more information
 */
class ErrorCollection implements Countable, JsonSerializable
{
    private $_errors;

    // phpcs:ignore PEAR.Commenting.FunctionComment.Missing
    public function __construct($errorData)
    {
        $this->_errors =
                new ValidationErrorCollection($errorData);
    }

    /**
     * Return count of items in collection
     * Implements countable
     *
     * @return integer
     */
    #[\ReturnTypeWillChange]
    public function count()
    {
        return $this->deepSize();
    }

    /**
     * Returns all of the validation errors at all levels of nesting in a single, flat array.
     *
     * @return array
     */
    public function deepAll()
    {
        return $this->_errors->deepAll();
    }

    /**
     * Returns the total number of validation errors at all levels of nesting. For example,
     *if creating a customer with a credit card and a billing address, and each of the customer,
     * credit card, and billing address has 1 error, this method will return 3.
     *
     * @return integer size
     */
    public function deepSize()
    {
        $size = $this->_errors->deepSize();
        return $size;
    }

    /**
     * return errors for the passed key name
     *
     * @param string $key name
     *
     * @return mixed
     */
    public function forKey($key)
    {
        return $this->_errors->forKey($key);
    }

    /**
     * return errors for the passed html field.
     * For example, $result->errors->onHtmlField("transaction[customer][last_name]")
     *
     * @param string $field html element
     *
     * @return array
     */
    public function onHtmlField($field)
    {
        $pieces = preg_split("/[\[\]]+/", $field, 0, PREG_SPLIT_NO_EMPTY);
        $errors = $this;
        foreach (array_slice($pieces, 0, -1) as $key) {
            $errors = $errors->forKey(Util::delimiterToCamelCase($key));
            if (!isset($errors)) {
                return [];
            }
        }
        $finalKey = Util::delimiterToCamelCase(end($pieces));
        return $errors->onAttribute($finalKey);
    }

    /**
     * Returns the errors at the given nesting level (see forKey) in a single, flat array:
     *
     * <code>
     *   $result = Customer::create(...);
     *   $customerErrors = $result->errors->forKey('customer')->shallowAll();
     * </code>
     *
     * @return array
     */
    public function shallowAll()
    {
        return $this->_errors->shallowAll();
    }

    // phpcs:ignore PEAR.Commenting.FunctionComment.Missing
    public function __get($name)
    {
        $varName = "_$name";
        return isset($this->$varName) ? $this->$varName : null;
    }

    // phpcs:ignore PEAR.Commenting.FunctionComment.Missing
    public function __toString()
    {
        return sprintf('%s', $this->_errors);
    }

    /**
     * Implementation of JsonSerializable
     *
     * @return array
     */
    #[\ReturnTypeWillChange]
    public function jsonSerialize()
    {
        return $this->_errors->deepAll();
    }
}
