<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Asset Optimizer Library
 * 
 * Minifies and optimizes CSS and JavaScript files
 */
class Asset_optimizer {
    
    private $CI;
    private $cache_dir;
    private $minify_css = TRUE;
    private $minify_js = TRUE;
    private $combine_files = TRUE;
    
    public function __construct($config = array()) {
        $this->CI =& get_instance();
        $this->cache_dir = APPPATH . 'cache/assets/';
        
        // Create cache directory if it doesn't exist
        if (!is_dir($this->cache_dir)) {
            mkdir($this->cache_dir, 0755, TRUE);
        }
        
        // Load configuration
        if (isset($config['minify_css'])) {
            $this->minify_css = $config['minify_css'];
        }
        if (isset($config['minify_js'])) {
            $this->minify_js = $config['minify_js'];
        }
        if (isset($config['combine_files'])) {
            $this->combine_files = $config['combine_files'];
        }
    }
    
    /**
     * Minify CSS content
     * 
     * @param string $css CSS content
     * @return string Minified CSS
     */
    public function minify_css($css) {
        if (!$this->minify_css) {
            return $css;
        }
        
        // Remove comments
        $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
        
        // Remove unnecessary whitespace
        $css = preg_replace('/\s+/', ' ', $css);
        $css = preg_replace('/\s*{\s*/', '{', $css);
        $css = preg_replace('/;\s*/', ';', $css);
        $css = preg_replace('/\s*}\s*/', '}', $css);
        $css = preg_replace('/\s*,\s*/', ',', $css);
        $css = preg_replace('/\s*:\s*/', ':', $css);
        
        // Remove last semicolon before closing brace
        $css = preg_replace('/;(\s*})/', '$1', $css);
        
        return trim($css);
    }
    
    /**
     * Minify JavaScript content
     * 
     * @param string $js JavaScript content
     * @return string Minified JavaScript
     */
    public function minify_js($js) {
        if (!$this->minify_js) {
            return $js;
        }
        
        // Remove single-line comments
        $js = preg_replace('~//[^\r\n]*~', '', $js);
        
        // Remove multi-line comments
        $js = preg_replace('~/\*.*?\*/~s', '', $js);
        
        // Remove unnecessary whitespace
        $js = preg_replace('/\s+/', ' ', $js);
        $js = preg_replace('/\s*([{}();,=+\-*\/])\s*/', '$1', $js);
        
        return trim($js);
    }
    
    /**
     * Optimize CSS file
     * 
     * @param string $file_path Path to CSS file
     * @return string Optimized CSS content
     */
    public function optimize_css_file($file_path) {
        if (!file_exists($file_path)) {
            return '';
        }
        
        $content = file_get_contents($file_path);
        return $this->minify_css($content);
    }
    
    /**
     * Optimize JavaScript file
     * 
     * @param string $file_path Path to JS file
     * @return string Optimized JavaScript content
     */
    public function optimize_js_file($file_path) {
        if (!file_exists($file_path)) {
            return '';
        }
        
        $content = file_get_contents($file_path);
        return $this->minify_js($content);
    }
    
    /**
     * Get optimized asset with caching
     * 
     * @param string $type Asset type (css or js)
     * @param array $files Array of file paths
     * @return string Optimized asset content
     */
    public function get_optimized_asset($type, $files) {
        $cache_key = $type . '_' . md5(serialize($files));
        $cache_file = $this->cache_dir . $cache_key . '.' . $type;
        
        // Check if cached version exists and is newer than source files
        if (file_exists($cache_file)) {
            $cache_time = filemtime($cache_file);
            $newest_source = 0;
            
            foreach ($files as $file) {
                if (file_exists($file)) {
                    $newest_source = max($newest_source, filemtime($file));
                }
            }
            
            if ($cache_time > $newest_source) {
                return file_get_contents($cache_file);
            }
        }
        
        // Generate optimized content
        $content = '';
        foreach ($files as $file) {
            if (file_exists($file)) {
                if ($type === 'css') {
                    $content .= $this->optimize_css_file($file) . "\n";
                } else {
                    $content .= $this->optimize_js_file($file) . "\n";
                }
            }
        }
        
        // Save to cache
        file_put_contents($cache_file, $content);
        
        return $content;
    }
    
    /**
     * Clear asset cache
     * 
     * @param string $type Optional asset type to clear
     */
    public function clear_cache($type = NULL) {
        $files = glob($this->cache_dir . '*');
        
        foreach ($files as $file) {
            if (is_file($file)) {
                if ($type === NULL || strpos($file, '.' . $type) !== FALSE) {
                    unlink($file);
                }
            }
        }
    }
    
    /**
     * Get cache size
     * 
     * @return array Cache statistics
     */
    public function get_cache_stats() {
        $files = glob($this->cache_dir . '*');
        $total_size = 0;
        $file_count = 0;
        
        foreach ($files as $file) {
            if (is_file($file)) {
                $total_size += filesize($file);
                $file_count++;
            }
        }
        
        return array(
            'file_count' => $file_count,
            'total_size' => $total_size,
            'total_size_formatted' => $this->format_bytes($total_size)
        );
    }
    
    /**
     * Format bytes to human readable format
     * 
     * @param int $bytes Number of bytes
     * @return string Formatted string
     */
    private function format_bytes($bytes) {
        $units = array('B', 'KB', 'MB', 'GB');
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        
        $bytes /= pow(1024, $pow);
        
        return round($bytes, 2) . ' ' . $units[$pow];
    }
}
