<?php


namespace AutoAdmin\Bundle\Media\Service;


use AutoAdmin\Bundle\Admin\Factory\ContentFactory;
use AutoAdmin\Bundle\Core\Helper\DoctrineHelper;
use AutoAdmin\Bundle\Media\Mapper\MapperManager;
use AutoAdmin\Bundle\Media\Model\FileInterface;
use AutoAdmin\Bundle\Media\Model\MediaInterface;
use AutoAdmin\Bundle\Media\Namer\NamerInterface;
use Symfony\Component\Filesystem\Filesystem;

class MediaManipulator
{
    protected ContentFactory $contentFactory;
    protected NamerInterface $namer;
    protected MapperManager $mapperManager;
    protected Filesystem $fileSystem;

    public function __construct(
        ContentFactory $contentFactory,
        NamerInterface $namer,
        MapperManager  $mapperManager,
        FileSystem     $fileSystem
    )
    {
        $this->contentFactory = $contentFactory;
        $this->namer = $namer;
        $this->mapperManager = $mapperManager;
        $this->fileSystem = $fileSystem;
    }

    public function fileExists(FileInterface $media): bool
    {
        $origFilename = $media->getFileName();
        if ($origFilename) {
            $mapper = $this->mapperManager->getMapper($media);
            $path = $mapper->getUploadPath($media) . DIRECTORY_SEPARATOR;

            return $this->fileSystem->exists($path . $media->getFileName());
        }

        return false;
    }

    public function duplicate(FileInterface $media, FileInterface $clone = null): ?MediaInterface
    {
        /** @var MediaInterface $newMedia */
        $newMedia = $clone ?? $this->contentFactory->createEntity(DoctrineHelper::removeProxyPrefix(get_class($media)));
        // if this media is a file, duplicate it
        if ($newMedia instanceof FileInterface) {
            $mapper = $this->mapperManager->getMapper($media);
            $path = $mapper->getUploadPath($media).DIRECTORY_SEPARATOR;

            // generate new filename
            $origFilename = $media->getFileName();
            if ($origFilename) {
                $newFilename = $this->namer->generateName($origFilename);
                $newMedia->setFileName($newFilename);
                $newMedia->setOriginalName($newFilename);

                // duplicate file
                if ($this->fileSystem->exists($path.$origFilename)) {
                    $this->fileSystem->copy($path.$origFilename, $path.$newMedia->getFileName());
                }
            } else {
                $newMedia = null;
            }
        }

        return $newMedia;
    }
}
