<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Plugins\ImageGraph\StaticGraph;

use Piwik\Piwik;
class HorizontalBar extends \Piwik\Plugins\ImageGraph\StaticGraph\GridGraph
{
    public const INTERLEAVE = 0.3;
    public const PADDING_CHARS = ' ';
    public const LEGEND_SQUARE_WIDTH = 11;
    public const MIN_SPACE_BETWEEN_HORIZONTAL_VALUES = 5;
    public const LOGO_MIN_RIGHT_MARGIN = 3;
    public function renderGraph()
    {
        $verticalLegend = \false;
        // create resized copies of logo to match maximum width / height
        foreach ($this->abscissaLogos as &$logoPath) {
            $logoPath = $this->createResizedImageCopyIfNeeded($logoPath);
            list($logoWidth, $logoHeight) = self::getLogoSize($logoPath);
            $logoPathToHeight[$logoPath] = $logoHeight;
        }
        // determine the maximum logo width & height
        list($maxLogoWidth, $maxLogoHeight) = self::getMaxLogoSize($this->abscissaLogos);
        // truncate report
        $graphHeight = $this->getGraphBottom($horizontalGraph = \true) - $this->getGridTopMargin($horizontalGraph = \true, $verticalLegend);
        list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
        list($ordinateMaxWidth, $ordinateMaxHeight) = $this->getMaximumTextWidthHeight($this->ordinateSeries);
        $numberOfSeries = count($this->ordinateSeries);
        $ordinateMaxHeight = $ordinateMaxHeight * $numberOfSeries;
        $textMaxHeight = $abscissaMaxHeight > $ordinateMaxHeight ? $abscissaMaxHeight : $ordinateMaxHeight;
        $minLineWidth = ($textMaxHeight > $maxLogoHeight ? $textMaxHeight : $maxLogoHeight) + self::MIN_SPACE_BETWEEN_HORIZONTAL_VALUES * $numberOfSeries;
        $maxNumOfValues = floor($graphHeight / $minLineWidth);
        $abscissaSeriesCount = count($this->abscissaSeries);
        if ($maxNumOfValues < $abscissaSeriesCount - 1) {
            $sumOfOthers = array();
            $truncatedOrdinateSeries = array();
            $truncatedAbscissaLogos = array();
            $truncatedAbscissaSeries = array();
            foreach ($this->ordinateSeries as $column => $data) {
                $truncatedOrdinateSeries[$column] = array();
                $sumOfOthers[$column] = 0;
            }
            $i = 0;
            for (; $i < $maxNumOfValues; $i++) {
                foreach ($this->ordinateSeries as $column => $data) {
                    $truncatedOrdinateSeries[$column][] = $data[$i];
                }
                $truncatedAbscissaLogos[] = isset($this->abscissaLogos[$i]) ? $this->abscissaLogos[$i] : null;
                $truncatedAbscissaSeries[] = $this->abscissaSeries[$i];
            }
            for (; $i < $abscissaSeriesCount; $i++) {
                foreach ($this->ordinateSeries as $column => $data) {
                    $sumOfOthers[$column] += $data[$i];
                }
            }
            foreach ($this->ordinateSeries as $column => $data) {
                $truncatedOrdinateSeries[$column][] = $sumOfOthers[$column];
            }
            $truncatedAbscissaSeries[] = Piwik::translate('General_Others');
            $this->abscissaSeries = $truncatedAbscissaSeries;
            $this->ordinateSeries = $truncatedOrdinateSeries;
            $this->abscissaLogos = $truncatedAbscissaLogos;
        }
        // blank characters are used to pad labels so the logo can be displayed
        $paddingText = '';
        $paddingWidth = 0;
        if ($maxLogoWidth > 0) {
            while ($paddingWidth < $maxLogoWidth + self::LOGO_MIN_RIGHT_MARGIN) {
                $paddingText .= self::PADDING_CHARS;
                list($paddingWidth, $paddingHeight) = $this->getTextWidthHeight($paddingText);
            }
        }
        // determine the maximum label width according to the minimum comfortable graph size
        $gridRightMargin = $this->getGridRightMargin($horizontalGraph = \true);
        $minGraphSize = ($this->width - $gridRightMargin) / 2;
        $metricLegendWidth = 0;
        foreach ($this->ordinateLabels as $column => $label) {
            list($textWidth, $textHeight) = $this->getTextWidthHeight($label);
            $metricLegendWidth += $textWidth;
        }
        $legendWidth = $metricLegendWidth + (self::HORIZONTAL_LEGEND_LEFT_MARGIN + self::LEGEND_SQUARE_WIDTH) * $numberOfSeries;
        if ($this->showLegend) {
            if ($legendWidth > $minGraphSize) {
                $minGraphSize = $legendWidth;
            }
        }
        $gridLeftMarginWithoutLabels = $this->getGridLeftMargin($horizontalGraph = \true, $withLabel = \false);
        $labelWidthLimit = $this->width - $gridLeftMarginWithoutLabels - $gridRightMargin - $paddingWidth - $minGraphSize;
        // truncate labels if needed
        foreach ($this->abscissaSeries as &$label) {
            $label = $this->truncateLabel($label, $labelWidthLimit);
        }
        $gridLeftMarginBeforePadding = $this->getGridLeftMargin($horizontalGraph = \true, $withLabel = \true);
        // pad labels for logo space
        foreach ($this->abscissaSeries as &$label) {
            $label .= $paddingText;
        }
        $this->initGridChart($displayVerticalGridLines = \false, $bulletType = LEGEND_FAMILY_BOX, $horizontalGraph = \true, $showTicks = \false, $verticalLegend);
        $valueColor = $this->textColor;
        $this->pImage->drawBarChart(array('DisplayValues' => \true, 'Interleave' => self::INTERLEAVE, 'DisplayR' => $valueColor['R'], 'DisplayG' => $valueColor['G'], 'DisplayB' => $valueColor['B']));
        //        // display icons
        $graphData = $this->pData->getData();
        $numberOfRows = count($this->abscissaSeries);
        $logoInterleave = $this->getGraphHeight(\true, $verticalLegend) / $numberOfRows;
        for ($i = 0; $i < $numberOfRows; $i++) {
            if (isset($this->abscissaLogos[$i])) {
                $currentLogoPath = $this->abscissaLogos[$i];
                if (isset($logoPathToHeight[$currentLogoPath])) {
                    $logoHeight = $logoPathToHeight[$currentLogoPath];
                    $pathInfo = pathinfo($currentLogoPath);
                    $logoExtension = strtoupper($pathInfo['extension']);
                    $drawingFunction = 'drawFrom' . $logoExtension;
                    $logoYPosition = $logoInterleave * $i + $this->getGridTopMargin(\true, $verticalLegend) + $graphData['Axis'][1]['Margin'] - $logoHeight / 2 + 1;
                    if (method_exists($this->pImage, $drawingFunction)) {
                        $this->pImage->{$drawingFunction}($gridLeftMarginBeforePadding, $logoYPosition, $currentLogoPath);
                    }
                }
            }
        }
    }
}
