<?php

namespace AppBundle\Command;

use AppBundle\Enum\MediaType;
use Cocur\Slugify\Slugify;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;

/**
 * Update the filename of every media (DB & filesystem),
 * in order to remove special characters.
 * @author Bastien Gatellier <contact@bgatellier.fr>
 */
class SlugifyMediaFilenameCommand extends ContainerAwareCommand
{
    /**
     * 
     */
    protected function configure()
    {
        $this
            ->setName('cgenial:slugify:media')
            ->setDescription("Update the filename of every media (DB & filesystem), in order to remove special characters.");
    }

    /**
     *
     * @param InputInterface $input
     * @param OutputInterface $output
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $em = $this->getContainer()->get("doctrine.orm.entity_manager");
        $errors = [];
        $slugify = new Slugify();
        $filesystem = new Filesystem();

        // Get the pictures and PDF from the database
        $medias = $em->getRepository('AppBundle:Media')->findByType([MediaType::PDF, MediaType::PICTURE]);

        // Create a new progress bar
        $progress = new ProgressBar($output, count($medias));

        // Start and displays the progress bar
        $progress->start();

        foreach ($medias as $media) {
            $path = $media->getPath();
            $absolutePathCurrent = $media->getAbsolutePath();

            // Algorithm:
            // 1. Slit the filename according to the first -: separate unique identifier from original filename
            // 2. Split the remaining filename according to the last .: separate original filename from extension
            // 3. Slugify the original filename
            // 4. Concatenate the 3 parts (unique identifier, slugified filename and extension)
            // 5. Try to copy the file on the filesystem to the new filename
            // 6. Remove the old file if the copy is successful
            // 7. Update database  if the copy is successful or file does not exists

            // 1. Slit the filename according to the first -: separate unique identifier from original filename
            $firstDashPosition = strpos($path, '-');
            $uniqueId = substr($path, 0, $firstDashPosition);
            $filename = substr($path, $firstDashPosition + 1);

            // 2. Split the remaining filename according to the last .: separate original filename from extension
            $lastDotPosition = strrpos($filename, '.');
            $extension = substr($filename, $lastDotPosition + 1);
            $filename = substr($filename, 0, $lastDotPosition);
            
            // 3. Slugify the original filename
            $filenameSlugified = $slugify->slugify($filename);

            // 4. Concatenate the 3 parts (unique identifier, slugified filename and extension)
            $media->setPath($uniqueId . '-' . $filenameSlugified . '.' . $extension);

            // 5. Try to copy the file on the filesystem to the new filename
            try {
                $filesystem->copy($absolutePathCurrent, $media->getAbsolutePath(), true);

                // 6. Remove the old file if the copy is successful
                try {
                    $filesystem->remove($absolutePathCurrent, $media->getAbsolutePath());
                } catch (IOException $e) {
                   $errors[] = $em->getMessage();
                }

                // 7. Update database if the copy is successful
                $em->persist($media);
            } catch (FileNotFoundException $e) {
                // 7. Update database if the file does not exists
                $em->persist($media);
            } catch (IOException $e) {
                $errors[] = $e->getMessage();
            }

            $progress->advance();
        }

        $em->flush();

        // Ensure that the progress bar is at 100%
        $progress->finish();

        if ($errors) {
            foreach ($errors as $errorMessage) {
                $output->writeln($errorMessage);
            }
        }
    }
}
