<?php

namespace AdminStarterPack;

if (!defined('WPINC')) { die; }

/**
 * Forked & modified from zacscott/wpcom-cdn.php
 */

class PhotonCDN {
    
    private static $_instance;
    private $options = [];
    private $exclude_list;
    private $quality;
    private $selectedServer;
    
    /**
     * point to WP.com image servers; i0.wp.com, i1.wp.com, i2.wp.com, i3.wp.com
     */
    const MAXSRV = 4;
    
    public static function getInstance()
    {
        if (!self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    public function __construct() {
        
        $this->options = get_option('starterpack_options', []);
        
        $this->exclude_list = array_filter(array_map('trim', explode("\n", $this->options['use_free_img_cdn_exclude_list'] ?? '')));
        $this->quality = $this->options['use_free_img_cdn_compression_quality'];
        
        add_action('wp_head', [$this, 'printDnsPrefetch'], 0);
        $this->startBuffer();

    }

    protected function excludeKeywords($matches) {
        
        $excludeKeywords = $this->exclude_list;
        foreach ($excludeKeywords as $exclude) {
            if (!!$exclude && stristr($matches, $exclude) != false) {
                return true;
            }
        }
        return false;
        
    }

    // Processes the output buffer, replacing all matching images with URLs, pointing to wp.com
    public function processOutput($content) {

        // Get the content directory URL minus the http://
        $img_url = content_url();
        
        $img_url = str_replace([
            'http://',
            'https://'
        ], ['', ''], $img_url);
        
        return preg_replace_callback(
            '{'. $img_url .'/[^\/\s]+\/\S+\.(jpg|jpeg|png|gif|webp)}i',
            [$this, 'replaceUrl'],
            $content
        );
    }

    // Replace matched image URLs
    public function replaceUrl($matches) {
        
        if ($this->excludeKeywords($matches[0])) {
            return $matches[0];
        }
        
        // strip metadata
        $strip = 'all';
        $quality = $this->quality;
        
        // Grab the parsed image URL
        $url = isset($matches[0]) ? $matches[0] : '';
        
        // Select a random server and cache it for subsequent requests
        if ($this->selectedServer === null) {
            srand(crc32($url));
            $this->selectedServer = rand(0, self::MAXSRV - 1);
        }
        
        $cdnUrl = "i" . $this->selectedServer . ".wp.com";
        
        $final_url = "$cdnUrl/$url?quality=$quality&strip=$strip";
        
        return esc_attr($final_url);
        
    }
    
    // Print the DNS prefetch
    public function printDnsPrefetch() {
        if ($this->selectedServer === null) {
            srand();
            $this->selectedServer = rand(0, self::MAXSRV - 1);
        }
        
        $cdnUrl = "i" . $this->selectedServer . ".wp.com";
        $domain = "https://" . $cdnUrl;
        echo '<link rel="dns-prefetch" href="' . esc_url($domain) . '">';
        echo '<link rel="preconnect" href="' . esc_url($domain) . '" crossorigin>
';
    }

    // Start the output buffering
    public function startBuffer() {
        
        if (!is_admin()) {
            ob_start([$this, 'processOutput']);
            register_shutdown_function([$this, 'endBuffer']);
        }
        
    }

    public function endBuffer() {
        // Get the contents of the output buffer
        $this->buffer = ob_get_contents();
        // Clean the output buffer if it's active
        if (ob_get_length() > 0) {
            ob_end_clean();
        }
        // Process the modified content
        echo $this->buffer;
        // Flush the output buffer if it's active
        if (ob_get_length() > 0) {
            ob_end_flush();
        }
    }

}

