<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Catalog\Model\Layer\Filter\DataProvider;

use Magento\Catalog\Model\Layer\Filter\FilterInterface;

class Decimal
{
    const MIN_RANGE_POWER = 10;

    /**
     * @var int
     */
    private $max;

    /**
     * @var int
     */
    private $min;

    /**
     * @var int
     */
    private $range;

    /**
     * @var array
     */
    private $rangeItemsCount = [];

    /**
     * @var \Magento\Catalog\Model\ResourceModel\Layer\Filter\Decimal
     */
    private $resource;

    /**
     * @param \Magento\Catalog\Model\ResourceModel\Layer\Filter\Decimal $resource
     */
    public function __construct(\Magento\Catalog\Model\ResourceModel\Layer\Filter\Decimal $resource)
    {
        $this->resource = $resource;
    }

    /**
     * @param FilterInterface $filter
     * @return int
     */
    public function getRange(FilterInterface $filter)
    {
        $range = $this->range;
        if (!$range) {
            $maxValue = $this->getMaxValue($filter);
            $index = 1;
            do {
                $range = pow(10, strlen(floor($maxValue)) - $index);
                $items = $this->getRangeItemCounts($range, $filter);
                $index++;
            } while ($range > self::MIN_RANGE_POWER && count($items) < 2);
            $this->range = $range;
        }

        return $range;
    }

    /**
     * @param int $range
     * @return void
     */
    public function setRange($range)
    {
        $this->range = $range;
    }

    /**
     * Retrieve maximum value from layer products set
     *
     * @param FilterInterface $filter
     * @return float
     */
    public function getMaxValue(FilterInterface $filter)
    {
        if ($this->max === null) {
            $this->loadValues($filter);
        }

        return $this->max;
    }

    /**
     * Retrieve minimal value from layer products set
     *
     * @param FilterInterface $filter
     * @return float
     */
    public function getMinValue(FilterInterface $filter)
    {
        if ($this->min === null) {
            $this->loadValues($filter);
        }

        return $this->min;
    }

    /**
     * Retrieve information about products count in range
     *
     * @param int $range
     * @param FilterInterface $filter
     * @return mixed
     */
    public function getRangeItemCounts($range, FilterInterface $filter)
    {
        $count = array_key_exists($range, $this->rangeItemsCount) ? $this->rangeItemsCount[$range] : null;
        if ($count === null) {
            $count = $this->getResource()
                ->getCount($filter, $range);
            $this->rangeItemsCount[$range] = $count;
        }

        return $count;
    }

    /**
     * @return \Magento\Catalog\Model\ResourceModel\Layer\Filter\Decimal
     */
    public function getResource()
    {
        return $this->resource;
    }

    /**
     * @param FilterInterface $filter
     * @return mixed
     */
    private function loadValues(FilterInterface $filter)
    {
        list($min, $max) = $this->getResource()
            ->getMinMax($filter);
        $this->min = $min;
        $this->max = $max;

        return $this;
    }
}
