<?php

namespace AutoAdmin\Bundle\Media\Form\Type;

use AutoAdmin\Bundle\Media\EventListener\Form\MediaListener;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType as BaseFileType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\File;

/**
 * Inspired by : https://github.com/dustin10/VichUploaderBundle/blob/master/src/Form/Type/VichFileType.php
 */
class FileType extends AbstractType
{
    protected array $config;
    protected ManagerRegistry $doctrine;

    public function __construct(array $config, ManagerRegistry $doctrine)
    {
        $this->config = $config;
        $this->doctrine = $doctrine;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults(
            [
                'data_class' => $this->config['classes']['file'],
                'mime_types' => $this->config['mime_types']['file'],
                'mapping' => 'default',
                'title_options' => [
                    'required' => false,
                    'label' => 'media.file.title',
                    'translation_domain' => 'aa_admin',
                ],
                'file_options' => [
                    'label' => 'media.file.file',
                    'translation_domain' => 'aa_admin',
                ],
                'display_delete_button' => false,
            ]
        );
    }

    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        parent::buildView($view, $form, $options);

        $view->vars['mapping'] = $options['mapping'];
        $view->vars['max_upload_size'] = $this->getMaxFileUpload();
    }

    protected function getMaxFileUpload($RoundLength = 1): string
    {
        $bytes = $this->getMaxUploadSize();
        $kb = 1024;         // Kilobyte
        $mb = 1024 * $kb;   // Megabyte
        $gb = 1024 * $mb;   // Gigabyte
        $tb = 1024 * $gb;   // Terabyte

        if ($bytes < $kb) {
            if (!$bytes) {
                $bytes = '0';
            }

            return (($bytes + 1) - 1) . ' B';
        } else {
            if ($bytes < $mb) {
                return round($bytes / $kb, $RoundLength) . ' KB';
            } else {
                if ($bytes < $gb) {
                    return round($bytes / $mb, $RoundLength) . ' MB';
                } else {
                    if ($bytes < $tb) {
                        return round($bytes / $gb, $RoundLength) . ' GB';
                    } else {
                        return round($bytes / $tb, $RoundLength) . ' TB';
                    }
                }
            }
        }
    }

    protected function getMaxUploadSize()
    {
        $sizes = array();
        $sizes[] = ini_get('upload_max_filesize');
        $sizes[] = ini_get('post_max_size');
        $sizes[] = ini_get('memory_limit');
        for ($x = 0; $x < count($sizes); $x++) {
            $unit = strtolower($sizes[$x][strlen($sizes[$x]) - 1]);
            $sizes[$x] = floatval($sizes[$x]);
            if ($unit == 'k') {
                $sizes[$x] *= 1024;
            } elseif ($unit == 'm') {
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
            } elseif ($unit == 'g') {
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
            } elseif ($unit == 't') {
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
                $sizes[$x] *= 1024;
            }
        }

        return min($sizes);
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        parent::buildForm($builder, $options);

        $builder->add(
            'file',
            BaseFileType::class,
            array_merge(
                [
                    'required' => $options['required'],
                    'label' => $options['label'],
                    'attr' => $options['attr'],
                    'translation_domain' => $options['translation_domain'],
                    'constraints' => $this->getConstraints($options),
                ],
                $options['file_options']
            )
        );

        $builder->add('title', TextType::class, $options['title_options']);

        $builder->addEventSubscriber(new MediaListener($this->doctrine));
    }

    private function getConstraints(array $options): array
    {
        $constraints = [];

        if (isset($options['mime_types'])) {
            $fileConstraint = new File();
            $fileConstraint->mimeTypes = $options['mime_types'];
            $constraints[] = $fileConstraint;
        }

        return $constraints;
    }

    public function getBlockPrefix(): string
    {
        return 'aa_file';
    }
}
