<?php

namespace Webapp\FileManagement\Controller;

use Shared\TransferSync\Entity\StatusDataEntry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Annotation\Route;
use Vich\UploaderBundle\Handler\DownloadHandler;
use Webapp\Core\Entity\Experiment;
use Webapp\Core\Entity\Platform;
use Webapp\FileManagement\Entity\ResponseFile;
use Webapp\FileManagement\Service\FileWriterService;
use Webapp\FileManagement\Service\WebappWriterService;
use Webapp\FileManagement\Voters\UserLinkedFileJobVoter;

/**
 * Class DownloadFileController.
 */
class DownloadFileController extends AbstractController
{
    /**
     * @Route("/api/download/response-files/{file}", name="downloadReturnFile")
     * @param ResponseFile $file
     * @param DownloadHandler $downloadHandler
     * @return Response
     */
    public function executeDownload(ResponseFile $file, DownloadHandler $downloadHandler): Response
    {
        $this->denyAccessUnlessGranted(UserLinkedFileJobVoter::DOWNLOAD, $file);
        $response = $downloadHandler->downloadObject($file, 'file');
        $response->headers->set('Content-Type', 'application/zip');
        return $response;
    }

    /**
     * @Route("/api/download/project/{project}", name="downloadProjectFile")
     * @param StatusDataEntry $project
     * @param FileWriterService $writerService
     * @return Response
     */
    public function exportProjectFile(StatusDataEntry $project, FileWriterService $writerService): Response
    {
        $response = new StreamedResponse(function () use ($writerService, $project) {
            $outputStream = fopen('php://output', 'wb');
            $zipStream = tmpfile();
            $writerService->constructProjectZipFile($project->getRequest(), stream_get_meta_data($zipStream)['uri']);
            stream_copy_to_stream(fopen(stream_get_meta_data($zipStream)['uri'], 'r'), $outputStream);
            fclose($zipStream);
        });
        $response->headers->set('Content-Type', 'application/zip');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $project->getRequest()->getName() . '.zip',
            iconv("UTF-8", "ASCII//TRANSLIT", $project->getRequest()->getName() . '.zip')
        ));
        return $response;
    }

    /**
     * @Route("/api/download/experiment/{experiment}", name="downloadExperimentFile")
     * @param Experiment $experiment
     * @param WebappWriterService $writerService
     * @return Response
     */
    public function exportExperimentFile(Experiment $experiment, WebappWriterService $writerService): Response
    {

        $response = new Response($writerService->constructExperimentXml($experiment));
        $response->headers->set('Content-Type', 'application/xml');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $experiment->getName() . '.xml',
            iconv("UTF-8", "ASCII//TRANSLIT", $experiment->getName())
        ));
        return $response;
    }

    /**
     * @Route("/api/download/platform/{platform}", name="downloadPlatformFile")
     * @param Platform $platform
     * @param WebappWriterService $writerService
     * @return Response
     */
    public function exportPlatformFile(Platform $platform, WebappWriterService $writerService): Response
    {

        $response = new Response($writerService->constructPlatformXml($platform));
        $response->headers->set('Content-Type', 'application/xml');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $platform->getName() . '.xml',
            iconv("UTF-8", "ASCII//TRANSLIT", $platform->getName())
        ));

        return $response;
    }

    /**
     * @Route("/api/download/platformWithData/{platform}", name="downloadPlatformWithDataFile")
     * @param Platform $platform
     * @param WebappWriterService $writerService
     * @return Response
     */
    public function exportPlatformWithDataFile(Platform $platform, WebappWriterService $writerService): Response
    {

        $response = new Response($writerService->constructPlatformWithDataXml($platform));
        $response->headers->set('Content-Type', 'application/xml');
        $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(
            HeaderUtils::DISPOSITION_ATTACHMENT,
            $platform->getName() . '.xml',
            iconv("UTF-8", "ASCII//TRANSLIT", $platform->getName())
        ));

        return $response;
    }
}
