<?php

namespace Plainwork\Http;

class Download
{
    private array $downloadDataFuncs = [];

    public function addDownloadDataFunc(callable $func): self
    {
        $this->downloadDataFuncs[] = $func;

        return $this;
    }

    public function downloadFile($file, $shortFile = null)
    {
        if (ob_get_contents()) {
            ob_end_clean();
        }

        if (null === $shortFile) {
            $shortFile = basename($file);
        }

        $fileSize = filesize($file);

        header('Type: application/force-download');
        header('Content-Type: application/force-download');
        header("Content-Length: $fileSize");
        header('Content-Transfer-Encoding: binary');
        header("Content-Disposition: attachment; filename=\"$shortFile\"");
        header('Pragma: public');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Connection: close');
        readfile($file);
        exit;
    }

    public function downloadData($filename, $data, $mime = 'application/octet-stream')
    {
        $func = [$this, 'doDownloadData'];
        foreach ($this->downloadDataFuncs as $decorator) {
            $func = fn($filename, $data, $mime) => $decorator($filename, $data, $mime, $func);
        }

        return $func($filename, $data, $mime);
    }

    public function doDownloadData($filename, $data, $mime = 'application/octet-stream')
    {
    // Try to determine if the filename includes a file extension.
    // We need it in order to set the MIME type
        if (false === strpos($filename, '.')) {
            return false;
        }

        if (! $mime) {
        // Load the mime types
            $mimes = array();

        // Grab the file extension
            $x = explode('.', $filename);
            $extension = end($x);

            // Set a default mime if we can't find it
            if (! isset($mimes[$extension])) {
                $mime = 'application/octet-stream';
            } else {
                $mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
            }
        }

        $contentDisposition = 'attachment';
        if ('text/calendar' == $mime) {
            $contentDisposition = 'inline';
        }

    // Generate the server headers
        header('Content-Type: "' . $mime . '"');
        header('Content-Disposition: ' . $contentDisposition . '; filename="' . $filename . '"');
        header('Expires: 0');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . strlen($data));

        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
            header('Pragma: public');
        } else {
            header('Pragma: no-cache');
        }

        exit($data);
    }
}
