private function prepare(string $filename, array $options = []): ?string
    {
        if (!empty($options)) {
            $this->validateOptions($options);
        }

        $result = null;

        if ($this->hasEventListeners('beforePrepare')) {
            $eventDetails = new \BearFramework\App\Assets\BeforePrepareEventDetails($filename, $options);
            $this->dispatchEvent('beforePrepare', $eventDetails);
            $filename = $eventDetails->filename;
            $options = $eventDetails->options;
        }

        if (strlen($filename) > 0 && is_file($filename)) {
            if (!isset($options['width']) && !isset($options['height'])) {
                $result = $filename;
            } else {
                $extension = pathinfo($filename, PATHINFO_EXTENSION);
                if ($extension === '') {
                    $extension = 'tmp';
                }
                if (isset($options['outputType'])) {
                    $extension = $options['outputType'];
                }
                $tempFilename = $this->app->data->getFilename('.temp/assets/' . md5(md5($filename) . md5(json_encode($options))) . '.' . $extension);
                if (!is_file($tempFilename)) {
                    $this->resize($filename, $tempFilename, [
                        'width' => (isset($options['width']) ? $options['width'] : null),
                        'height' => (isset($options['height']) ? $options['height'] : null)
                    ]);
                }
                $result = $tempFilename;
            }
        }
        if ($this->hasEventListeners('prepare')) {
            $eventDetails = new \BearFramework\App\Assets\PrepareEventDetails($filename, $options, $result);
            $this->dispatchEvent('prepare', $eventDetails);
            $result = $eventDetails->returnValue;
        }
        return $result;
    }