<?php
/**
 * DokuWiki Plugin pagestats (Helper Component)
 * Common functionality for page stats calculation
 */

if (!defined('DOKU_INC')) die();

class helper_plugin_pagestats extends DokuWiki_Plugin {
    private $cache = null;
    private $cacheTime = 3600; // Cache standardmäßig für 1 Stunde

    /**
     * Constructor - reads configuration
     */
    public function __construct() {
        // Get cache lifetime from configuration (if set)
        $cacheTime = $this->getConf('cacheTime');
        if (is_numeric($cacheTime)) {
            $this->cacheTime = (int)$cacheTime;
        }
        
        // Wenn die Cache-Zeit geändert wurde, Cache löschen
        $optionChanged = false;
        if (isset($_POST['config']['plugin']['pagestats']['cacheTime']) && 
            $_POST['config']['plugin']['pagestats']['cacheTime'] != $this->cacheTime) {
            $optionChanged = true;
        }
        
        // Wenn Namensräume ausschließen geändert wurde, Cache löschen
        if (isset($_POST['config']['plugin']['pagestats']['excludeNamespaces'])) {
            $optionChanged = true;
        }
        
        if ($optionChanged) {
            $this->clearCache();
        }
    }

    /**
     * Calculate all stats at once to avoid multiple directory scans
     *
     * @return array Associative array with all statistics
     */
    public function getStats() {
        // Check if we have cached values
        $cache = $this->loadCache();
        if ($cache !== null) {
            return $cache;
        }

        // Calculate all stats
        try {
            $dataPathPages = DOKU_INC . 'data/pages';
            $dataPathMedia = DOKU_INC . 'data/media';
            
            $excludeNamespaces = array_map('trim', explode(',', $this->getConf('excludeNamespaces')));

            $stats = [
                'PAGESTATSPAGE' => 0,
                'PAGESTATSMB' => 0,
                'MEDIASTATSPAGE' => 0,
                'MEDIASTATSMB' => 0
            ];

            // Pages stats
            list($count, $size) = $this->calculateStats($dataPathPages, 'txt', $excludeNamespaces);
            $stats['PAGESTATSPAGE'] = $count;
            $stats['PAGESTATSMB'] = round($size / (1024 * 1024), 2);

            // Media stats
            list($count, $size) = $this->calculateStats($dataPathMedia, '', $excludeNamespaces);
            $stats['MEDIASTATSPAGE'] = $count;
            $stats['MEDIASTATSMB'] = round($size / (1024 * 1024), 2);

            // Cache the results
            $this->saveCache($stats);

            return $stats;
        } catch (Exception $e) {
            $this->log('pagestats', 'Error calculating stats: '.$e->getMessage(), DOKU_INC.'pagestats_error.log');
            return [
                'PAGESTATSPAGE' => 0,
                'PAGESTATSMB' => 0,
                'MEDIASTATSPAGE' => 0,
                'MEDIASTATSMB' => 0
            ];
        }
    }

    /**
     * Calculate both count and size in one iteration
     *
     * @param string $path Directory path
     * @param string $extension File extension to filter, empty for all
     * @param array $excludeNamespaces Namespaces to exclude
     * @return array [count, size]
     */
    private function calculateStats($path, $extension, $excludeNamespaces = []) {
        if (!is_dir($path)) return [0, 0];

        $count = 0;
        $totalSize = 0;
        
        try {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS)
            );

            foreach ($iterator as $file) {
                // Skip if not a file or doesn't match extension
                if (!$file->isFile() || ($extension !== '' && $file->getExtension() !== $extension)) {
                    continue;
                }
                
                // Skip if in excluded namespace
                $relativePath = str_replace($path, '', $file->getPathname());
                $shouldExclude = false;
                
                foreach ($excludeNamespaces as $ns) {
                    if (empty($ns)) continue;
                    if (strpos($relativePath, '/'.$ns.'/') !== false) {
                        $shouldExclude = true;
                        break;
                    }
                }
                
                if ($shouldExclude) continue;
                
                // Count and add size
                $count++;
                $totalSize += $file->getSize();
            }
        } catch (Exception $e) {
            // Log error but continue with what we have
            $this->log('pagestats', 'Error scanning directory: '.$e->getMessage(), DOKU_INC.'pagestats_error.log');
        }

        return [$count, $totalSize];
    }

    /**
     * Save stats to cache
     * 
     * @param array $stats The stats to cache
     */
    private function saveCache($stats) {
        if ($this->cacheTime <= 0) return; // Caching disabled
        
        $cacheFile = $this->getCacheFilename();
        $data = [
            'time' => time(),
            'stats' => $stats
        ];
        
        io_saveFile($cacheFile, serialize($data));
    }

    /**
     * Load stats from cache if available and not expired
     * 
     * @return array|null Stats or null if cache invalid/expired
     */
    private function loadCache() {
        if ($this->cacheTime <= 0) return null; // Caching disabled
        if ($this->cache !== null) return $this->cache; // Already loaded
        
        $cacheFile = $this->getCacheFilename();
        
        if (!file_exists($cacheFile)) return null;
        
        $data = unserialize(io_readFile($cacheFile, false));
        
        if (!$data || !isset($data['time']) || !isset($data['stats'])) {
            return null;
        }
        
        // Check if cache expired
        if (time() - $data['time'] > $this->cacheTime) {
            return null;
        }
        
        $this->cache = $data['stats'];
        return $this->cache;
    }

    /**
     * Get the cache filename
     * 
     * @return string Full path to cache file
     */
    private function getCacheFilename() {
        return DOKU_INC . 'data/cache/pagestats.cache';
    }

    /**
     * Simple logging function
     * 
     * @param string $plugin Plugin name
     * @param string $message Log message
     * @param string $file Log file
     */
    private function log($plugin, $message, $file) {
        $time = date('Y-m-d H:i:s');
        $logline = "[$time] [$plugin] $message\n";
        io_saveFile($file, $logline, true);
    }

    /**
     * Clear the cache (e.g. if called from admin)
     */
    public function clearCache() {
        $cacheFile = $this->getCacheFilename();
        if (file_exists($cacheFile)) {
            @unlink($cacheFile);
        }
        $this->cache = null;
    }
}