<?php

namespace Lightscale\LaralightSvg;

use Illuminate\Support\Facades\Cache;
use Illuminate\Cache\Repository;

class SvgCollectionState
{
    protected int $createdAt;
    protected ?string $hash;
    protected array $existing;
    protected array $pending;
    protected string $svg;

    public function __construct(
        protected readonly string $name,
    ) {}

    protected function arrayToMap(array $arr): array
    {
        $result = [];
        foreach($arr as $val) {
            $result[$val] = $val;
        }
        return $result;
    }

    public function pull(): void
    {
        $data = $this->cache()->get($this->cacheKey());
        $this->svg = $data['svg'] ?? '';
        $this->createdAt = $data['createdAt'] ?? time();
        $this->existing = static::arrayToMap($data['existing'] ?? []);
        $this->pending = static::arrayToMap($data['pending'] ?? []);
        $this->hash = $data['hash'] ?? null;
    }

    public function push(): void
    {
        $data = [
            'createdAt' => $this->createdAt,
            'hash' => $this->hash,
            'existing' => array_values($this->existing),
            'pending' => array_values($this->pending),
            'svg' => $this->svg,
        ];
        $this->cache()->put($this->cacheKey(), $data);
    }

    public function getPending(): array
    {
        if (!isset($this->pending)) $this->pull();
        return $this->pending;
    }

    public function getExisting(): array
    {
        if (!isset($this->existing)) $this->pull();
        return $this->existing;
    }

    public function getFullSvg(): string
    {
        if (!isset($this->svg)) $this->pull();
        return $this->svg;
    }

    public function setFullSvg(string $svg, bool $push = true): void
    {
        $this->svg = $svg;
        if ($push) $this->push();
    }

    public function isExisting(string $svg): bool
    {
        return !empty($this->getExisting()[$svg] ?? null);
    }

    public function concatExisting(array $svgs, bool $push = true): void
    {
        $this->existing = [
           ...$this->existing,
           ...static::arrayToMap($svgs),
        ];
        if ($push) $this->push();
    }

    public function clearExisting(bool $push = true): void
    {
        $this->existing = [];
        if($push) $this->push();
    }

    public function isPending(string $svg): bool
    {
        return !empty($this->getPending()[$svg] ?? null);
    }

    public function hasPending(): bool
    {
        return !empty($this->getPending());
    }

    public function addPending(string $svg): void
    {
        $this->pending[$svg] = $svg;
        $this->push();
    }

    public function clearPending(bool $push = true): void
    {
        $this->pending = [];
        if($push) $this->push();
    }

    public function addSvg(string $svg): void
    {
        if (!$this->isExisting($svg) && !$this->isPending($svg)) {
            $this->addPending($svg);
        }
    }

    public function clear(): void
    {
        $this->cache()->forget($this->cacheKey());
    }

    protected function cache(): Repository
    {
        return Cache::store(config('svg.cache_store'));
    }

    protected function cacheKey(): string
    {
        return SvgServiceProvider::NAMESPACE . '::' . $this->name;
    }

    public function getHash(): ?string
    {
        return $this->hasPending() ? null : $this->hash;
    }

    public function updateHash(): void
    {
        $data = $this->existing;
        sort($data);
        $data[] = $this->createdAt;
        $this->hash = substr(md5(json_encode($data)), 0, 10);
    }

}