<?php
namespace Grav\Plugin;
use Grav\Common\Plugin;
use Composer\Autoload\ClassLoader;
// use Grav\Common\Page\Collection;
// use Grav\Common\Yaml;


class LoadImagesPlugin extends Plugin
{
    /**
     * @var array
     */
    protected $imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

    /**
     * @var string
     */
    protected $cacheDir;
    
    public static function getSubscribedEvents()
    {
        return [
            'onPluginsInitialized' => [
                ['autoload', 100001],
                ['onPluginsInitialized', 0]
            ],
            // 必须添加这行才能激活模板注册
            'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0]
        ];
    }

     /**
     * Add current directory to twig lookup paths.
     */
    public function onTwigTemplatePaths()
    {   $path = str_replace('\\', '/', __DIR__ . '/templates');
        $this->grav['twig']->twig_paths[] = $path;
        // $this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
        // 添加主题覆盖路径（可选）
        // $theme = $this->grav['theme'];
        // $this->grav['twig']->twig_paths[] = "user/plugins/loadimages/templates";
    }

    /**
     * [onPluginsInitialized:100000] Composer autoload.
     *
     * @return ClassLoader
     */
    public function autoload()
    {
        return require __DIR__ . '/vendor/autoload.php';
    }

    /**
     * Initialize configuration
     */
    public function onPluginsInitialized()
    {
        if ($this->isAdmin()) {
            $this->active = false;
            return;
        }

        $uri = $this->grav['uri'];
        $route = $this->config->get('plugins.loadimages.route') ?? '/loadimages';

        if ($uri->path() === $route) {
            $this->handleRequest();
        }
    }

    private function handleRequest()
    {
        $this->cacheDir = GRAV_ROOT . '/images/cache/';
        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
        $this->loadImages();
    }


    // 生成缩略图，返回图片信息列表（包含EXIF信息）
    private function loadImages()
    {
        $page = max(1, (int) ($_GET['page'] ?? 1));
        $limit = min(100, max(1, (int) ($_GET['limit'] ?? 50)));
        $category = $this->sanitizeCategory($_GET['category'] ?? '');
        $categoryList = (int) ($_GET['categorylist'] ?? 0);
        $sort = $this->sanitizeSortField($_GET['sort'] ?? 'date');
        $order = $_GET['order'] ?? 'desc';

        if ($categoryList) {
            $categorydata = $this->getCategories();
            header('Content-Type: application/json');
            echo json_encode($categorydata, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
            exit();
        }
        $sortParam = $this->sanitizeSortField($sort);
        $orderParam = ($order === 'asc') ? 'asc' : 'desc';
        // $cacheKey = md5('images_' . $category);
        $cacheKey = md5('images_' . $category . '_' . $sortParam . '_' . $orderParam);
        $cache = $this->grav['cache'];

        if ($this->config->get('plugins.loadimages.cache_enabled') && $imagesData = $cache->fetch($cacheKey)) {
            $total = count($imagesData);
        } else {
            if ($category === 'all') {
                // $imagesData = $this->processImagesAll($sort, $order);
                $imagesData = $this->processImagesAll($sortParam, $orderParam);
            } else {
                $imagesData = $this->processImages($category, $sortParam, $orderParam); 
            }
            $total = count($imagesData);
            $cache->save($cacheKey, $imagesData);
        }

        $offset = ($page - 1) * $limit;
        $response = [
            'total' => $total,
            'images' => array_slice($imagesData, $offset, $limit)
        ];
        header('Content-Type: application/json');
        echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit();
    }

    // 获取类别列表
    private function getCategories()
    {
        $imagesPath = $this->config->get('plugins.loadimages.ImagesDatapath.Imagespath');
        $fullPath = GRAV_ROOT . '/' . ltrim($imagesPath, '/');

        if (!is_dir($fullPath)) {
            $this->grav['log']->error("图片目录不存在: {$fullPath}");
            return [];
        }

        $categories = [];
        try {
            $dirs = glob($fullPath . '/*', GLOB_ONLYDIR);
            foreach ($dirs as $dir) {
                $basename = basename($dir);
                $slug = $this->generateSlug($basename);
                $categories[] = [
                    'slug' => $slug,
                    'name' => $basename,
                    'url' => $this->grav['base_url'] . str_replace(GRAV_ROOT, '', $dir)
                ];
            }
            usort($categories, function($a, $b) {
                return strcmp($a['name'], $b['name']);
            });
        } catch (\Exception $e) {
            $this->grav['log']->error("获取分类失败: " . $e->getMessage());
        }
        return $categories;
    }

    private function sanitizeSortField($field)
    {
        $allowed = ['date', 'name', 'category'];
        return in_array($field, $allowed) ? $field : 'date';
    }

    private function generateSlug($string, $existingSlugs = [])
    {
        $baseSlug = preg_replace('/[^a-z0-9]+/', '-', strtolower($string));
        $baseSlug = trim($baseSlug, '-');
        $slug = $baseSlug;
        $counter = 1;
        while (in_array($slug, $existingSlugs)) {
            $slug = $baseSlug . '-' . substr(md5($string), 0, 4);
        }
        return $slug ?: 'uncategorized';
    }

    // 递归收集所有图片（支持排序参数）
    private function processImagesAll($sort, $order)
    {
        $basePath = $this->grav['config']->get('plugins.loadimages.ImagesDatapath.Imagespath');
        $fullPath = GRAV_ROOT . $basePath;
        $images = [];
        $this->collectImagesRecursively($fullPath, $images, $basePath);
        $this->sortImages($images, $sort, $order);
        return $images;
    }

    // 递归方法：收集图片（加入EXIF信息）
    private function collectImagesRecursively($dir, &$images, $basePath)
    {
        $excludePatterns = $this->config->get('plugins.loadimages.exclude_patterns') ?? [];
        foreach ($excludePatterns as $pattern) {
            if (preg_match($pattern, $dir)) {
                return;
            }
        }

        $entries = scandir($dir);
        foreach ($entries as $entry) {
            if ($entry === '.' || $entry === '..') continue;

            $fullEntryPath = $dir . DIRECTORY_SEPARATOR . $entry;

            if (is_dir($fullEntryPath)) {
                $this->collectImagesRecursively($fullEntryPath, $images, $basePath);
            } else {
                $ext = strtolower(pathinfo($fullEntryPath, PATHINFO_EXTENSION));
                if (in_array($ext, $this->imageTypes)) {
                    $exif = @exif_read_data($fullEntryPath, 'ANY_TAG', true);
                    if ($exif === false) {
                        $exif = [];
                    }
                    $imageInfo = $this->extractImageInfo($fullEntryPath, $exif, $basePath);
                    $imageInfo['thumbnailUrl'] = $this->handleThumbnail($fullEntryPath);
                    $images[] = $imageInfo;
                }
            }
        }
    }

    // 按分类返回图片信息（支持排序）
    private function processImages($category, $sort = 'date', $order = 'desc')
    {
        $basePath = $this->config->get('plugins.loadimages.ImagesDatapath.Imagespath');
        $fullPath = GRAV_ROOT . $basePath . ($category ? '/' . $category : '');

        if (!is_dir($fullPath)) {
            return [];
        }

        $images = [];
        $files = glob($fullPath . '/*.{'.implode(',', $this->imageTypes).'}', GLOB_BRACE);
        foreach ($files as $file) {
            if (!$this->isValidImage($file)) continue;

            $exif = @exif_read_data($file, 'ANY_TAG', true);
            if ($exif === false) {
                $exif = [];
            }
            $imageInfo = $this->extractImageInfo($file, $exif, $basePath);
            $imageInfo['thumbnailUrl'] = $this->handleThumbnail($file);
            $images[] = $imageInfo;
        }

        $this->sortImages($images, $sort, $order); 
        return $images;
    }

    private function sortImages(&$images, $sort, $order)
    {
        usort($images, function($a, $b) use ($sort, $order) {
            if ($sort === 'date') {
                $cmp = $a['timestamp'] - $b['timestamp'];
            } elseif ($sort === 'name') {
                $cmp = strcmp($a['name'], $b['name']);
            } elseif ($sort === 'category') {
                $cmp = strcmp($a['category'], $b['category']);
            } else {
                $cmp = 0;
            }
            return ($order === 'desc') ? -$cmp : $cmp;
        });
    }

    // 从EXIF读取详细信息
    private function extractImageInfo($path, $exif, $basePath)
    {
        $relativePath = str_replace(GRAV_ROOT . '/' . ltrim($basePath, '/'), '', $path);
        $category = trim(dirname($relativePath), '/');

        $size = @getimagesize($path);
        $filemtime = filemtime($path);
        $ctime = @filectime($path) ?: $filemtime; // 取创建时间，若 unavailable 使用修改时间

        // 从EXIF中提取描述、日期
        $description = '';
        if (isset($exif['COMMENT'])) {
            $description = is_array($exif['COMMENT']) ? implode(' ', $exif['COMMENT']) : $exif['COMMENT'];
        } elseif (isset($exif['ImageDescription'])) {
            $description = $exif['ImageDescription'];
        }

        $dateStr = $this->getImageDate($exif, $filemtime, $path);
        $timestamp = strtotime($dateStr);

        return [
            'url' => $this->grav['base_url'] . str_replace(GRAV_ROOT, '', $path),
            'name' => isset($exif['IFD0']['ImageDescription']) ? $exif['IFD0']['ImageDescription'] : pathinfo($path, PATHINFO_FILENAME),
            'category' => $category === '.' ? '' : $category,
            'width' => $size[0] ?? 0,
            'height' => $size[1] ?? 0,
            'date' => $dateStr,
            'timestamp' => $timestamp,
            'description' => $description,
            'thumbnailUrl' => ''
        ];
    }

    private function handleThumbnail($imagePath)
    {
        if (!$this->config->get('plugins.loadimages.thumbnail_enabled')) {
            return '';
        }

        $config = $this->config->get('plugins.loadimages.thumbnail');
        $thumbPath = $this->cacheDir . md5($imagePath) . '.jpg';

        if (!file_exists($thumbPath)) {
            try {
                $this->createThumbnail($imagePath, $thumbPath, $config['width'], $config['height'], $config['quality']);
                chmod($thumbPath, 0755);
            } catch (\Exception $e) {
                $this->grav['log']->error("缩略图生成失败: " . $e->getMessage());
                return '';
            }
        }

        return $this->grav['base_url'] . str_replace(GRAV_ROOT, '', $thumbPath);
    }

    private function createThumbnail($imagePath, $thumbPath, $width, $height, $quality)
    {
        list($origWidth, $origHeight, $type) = getimagesize($imagePath);
        $thumb = imagecreatetruecolor($width, $height);

        switch ($type) {
            case IMAGETYPE_JPEG:
                $source = imagecreatefromjpeg($imagePath);
                break;
            case IMAGETYPE_PNG:
                $source = imagecreatefrompng($imagePath);
                break;
            case IMAGETYPE_GIF:
                $source = imagecreatefromgif($imagePath);
                break;
            default:
                throw new \RuntimeException('Unsupported image type');
        }

        imagecopyresampled($thumb, $source, 0, 0, 0, 0, $width, $height, $origWidth, $origHeight);
        imagejpeg($thumb, $thumbPath, $quality);
        imagedestroy($thumb);
        imagedestroy($source);
    }

    private function getImageDate($exif, $filetime, $filepath)
    {
        // 1. 优先使用EXIF中的DateTimeOriginal
        if ($exif && isset($exif['EXIF']['DateTimeOriginal'])) {
            $dt = \DateTime::createFromFormat('Y:m:d H:i:s', $exif['EXIF']['DateTimeOriginal']);
            if ($dt !== false) {
                return $dt->format('Y-m-d H:i:s');
            }
        }
    
        // 2. 从文件名中提取日期（支持格式 YYYYMMDD 或 YYYYMMDD_HHMMSS）
        $filename = basename($filepath);
        if (preg_match('/(\d{4})(\d{2})(\d{2})(?:[_\-](\d{2})(\d{2})(\d{2}))?/', $filename, $matches)) {
            // 获取年、月、日和可选的时、分、秒
            $year = $matches[1];
            $month = $matches[2];
            $day = $matches[3];
            // $hour = isset($matches[4]) ? $matches[4] : '00';
            // $minute = isset($matches[5]) ? $matches[5] : '00';
            // $second = isset($matches[6]) ? $matches[6] : '00';
    
            // 构建时间字符串并返回
            // return "{$year}-{$month}-{$day} {$hour}:{$minute}:{$second}";
            return "{$year}-{$month}-{$day}";
        }
    
        // 3. 最后，使用文件的创建时间或修改时间
        return date('Y-m-d H:i:s', $filetime);
    }

    private function isValidImage($path)
    {
        $maxSize = $this->config->get('plugins.loadimages.performance.max_image_size') * 1024 * 1024;
        if (filesize($path) > $maxSize) {
            return false;
        }
        return @getimagesize($path) !== false;
    }

    private function sanitizeCategory($category)
    {
        $decoded = rawurldecode($category);
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            $decoded = iconv('UTF-8', 'GBK//IGNORE', $decoded);
        }
        return preg_replace('/[^\w\-\/\p{Han}]/u', '', $decoded);
    }

   
}
