<?php declare(strict_types=1);

namespace App\Captcha\Images;

use App\Captcha\Config\ImageHead as ImageHeadConfig;
use App\Captcha\Contracts\ImageLines;
use App\Captcha\Dto\Image as ImageDto;
use App\Captcha\Dto\ImageHead as ImageHeadDto;
use App\Captcha\Dto\Symbols;
use App\Captcha\Contracts\ImageHead;
use \App\Captcha\Contracts\Image as ImageContract;
use App\Captcha\Enums\SymbolType;
use App\Captcha\Contracts\ImageManager;

final class Head implements ImageHead
{
    public function __construct(
        private readonly ImageManager $imageManager,
        private readonly ImageLines $imageLines
    ) { }

    public function processing(Symbols $symbols, ImageHeadConfig $config): ImageHeadDto
    {
        $image = $this->imageManager->createImage($config->getWidth(), $config->getHeight());
        $image->insertBackground($config->randomBackground());

        $image = match ($symbols->getType()) {
            SymbolType::String => $this->processingString($image, $symbols, $config),
        };
        if ($config->getNumberLines() > 0) {
            $this->imageLines->processing(image: $image, colors: $config->getLineColors(), lines: $config->getNumberLines());
        }

        $image = new ImageDto(
            imageBase64: $image->encode(),
            width: $image->getWidth(),
            height: $image->getHeight()
        );

        return new ImageHeadDto(image: $image);
    }

    private function processingString(ImageContract $image, Symbols $symbols, ImageHeadConfig $config): Image
    {
        $textLeftPadding = $config->getTextPaddingLeft();
        $textTopPadding  = $config->getTextPaddingTop();
        $countSymbols    = count($symbols->getSuccess());
        $widthPrefix     = $image->getWidth() - $textLeftPadding;
        $imageHeight     = $image->getHeight() - $textTopPadding;

        foreach ($symbols->getSuccess() as $number => $symbol) {
            $marginLeft = $textLeftPadding + $number * $widthPrefix / $countSymbols;

            $image->addText(
                text:     $symbol,
                x:        intval($marginLeft),
                y:        $textTopPadding,
                size:     $this->randomFontSize($imageHeight),
                angle:    $config->randomAngle(),
                hexColor: $config->randomFontColor(),
                fontName: $config->randomFont()
            );
        }

        return $image;
    }

    private function randomFontSize(int $imageHeight): int
    {
        return mt_rand($imageHeight - 10, $imageHeight);
    }
}