<?php

/**
 * Frontend service handler for Havenlytics
 *
 * @package     Havenlytics
 * @subpackage  Includes
 * @copyright   Copyright (c) 2024, Havenlytics
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       2.0.0
 */

namespace HvnlyNab;

// Exit if accessed directly.
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Frontend Service Manager Class
 * 
 * Handles service registration, dependency management, and conditional loading.
 * Maintains full backward compatibility with existing code.
 *
 * @since 2.0.0
 */
class Frontend
{
    /**
     * Singleton instance
     *
     * @var self|null
     */
    private static $instance = null;

    /**
     * Registered service instances
     *
     * @var array
     */
    private $services = [];

    /**
     * Whether functions have been loaded
     *
     * @var bool
     */
    private $functions_loaded = false;

    /**
     * Flag to prevent infinite recursion
     *
     * @var bool
     */
    private static $registering = false;

    /**
     * Get singleton instance
     *
     * @return self
     */
    public static function get_instance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor
     */
    public function __construct()
    {
        // Prevent recursion
        if (self::$registering) {
            return;
        }
        
        self::$registering = true;
        self::register_services();
        $this->init_hooks();
        self::$registering = false;
    }

    /**
     * Get services list - BACKWARD COMPATIBLE VERSION
     * Returns simple array of class names like original
     *
     * @return array
     */
    public static function get_services()
    {
        /**
         * Filter: hvnly_frontend_services
         * 
         * Allows 3rd party plugins to modify frontend services.
         */
        return apply_filters('hvnly_frontend_services', array(
            Frontend\TemplateLoader::class,
            Frontend\Assets::class,
            Frontend\AjaxHandler::class,
            Frontend\SidebarAjaxHandler::class,
            Frontend\PropertyViewTracker::class,
            Frontend\PropertyCardRenderer::class, 
            Frontend\PropertySingleRenderer::class, 
            Frontend\EnhancedTemplateLoader::class,
            Frontend\LayoutManager::class,
            Frontend\Shortcodes\PropertySearch::class,
            Frontend\Shortcodes\PropertyGrid::class,
            Frontend\Shortcodes\PropertyList::class,
            Frontend\Shortcodes\FeaturedProperties::class,
            Frontend\Shortcodes\LegacyCompatibility::class,
            Frontend\Shortcodes\CacheInvalidation::class,
            Frontend\Shortcodes\Assets::class,
        ));
    }

    /**
     * Register services - EXACTLY LIKE ORIGINAL
     */
    public static function register_services()
    {
        $instance = self::get_instance();
        $services = self::get_services();
        
        foreach ($services as $class) {
            $instance->instantiate($class);
        }
        
        do_action('hvnly_frontend_services_registered');
    }

    /**
     * Instantiate a class - EXACTLY LIKE ORIGINAL
     *
     * @param string $class Class name.
     * @return object|null
     */
    private function instantiate($class)
    {
        if (!class_exists($class)) {
            return null;
        }
        
        // Special handling for LayoutManager to use singleton
        if ($class === Frontend\LayoutManager::class) {
            return Frontend\LayoutManager::instance();
        }
        
        // Prevent instantiating self recursively
        if ($class === self::class) {
            return null;
        }
        
        $service = new $class();
        
        // Store service for later retrieval
        $this->services[$class] = $service;
        
        return $service;
    }

    /**
     * Initialize hooks - EXACTLY LIKE ORIGINAL
     */
    private function init_hooks()
    {
        add_action('init', array($this, 'load_template_functions'));
    }

    /**
     * Load template functions - EXACTLY LIKE ORIGINAL
     */
    public function load_template_functions()
    {
        if ($this->functions_loaded) {
            return;
        }
        
        $functions_files = array(
            'template-functions.php',
            'template-hooks.php',
            'template-hook-functions.php',
            'property-functions.php',
            'layout-functions.php',
            'utility-functions.php',
            'ajax-functions.php',
            'shortcode-functions.php',
            'filter-sidebar-functions.php',
            'top-search-functions.php',
            'main-top-search-functions.php',
            'map-functions.php',
        );

        foreach ($functions_files as $file) {
            $file_path = HVNLYNAB_INCLUDES . '/Functions/' . $file;
            if (file_exists($file_path)) {
                require_once $file_path;
            }
        }
        
        $this->functions_loaded = true;
    }

    /**
     * Get a registered service instance
     *
     * @param string $class Class name
     * @return object|null
     */
    public function get_service($class)
    {
        return $this->services[$class] ?? null;
    }

    /**
     * Magic method for backward compatibility
     */
    public function __get($name)
    {
        $legacy_map = [
            'template_loader' => Frontend\TemplateLoader::class,
            'assets' => Frontend\Assets::class,
            'ajax_handler' => Frontend\AjaxHandler::class,
            'sidebar_ajax_handler' => Frontend\SidebarAjaxHandler::class,
            'view_tracker' => Frontend\PropertyViewTracker::class,
            'card_renderer' => Frontend\PropertyCardRenderer::class,
            'single_renderer' => Frontend\PropertySingleRenderer::class,
            'layout_manager' => Frontend\LayoutManager::class,
        ];
        
        if (isset($legacy_map[$name])) {
            return $this->get_service($legacy_map[$name]);
        }
        
        return null;
    }

    /**
     * Magic isset for backward compatibility
     */
    public function __isset($name)
    {
        $legacy_map = [
            'template_loader' => Frontend\TemplateLoader::class,
            'assets' => Frontend\Assets::class,
            'ajax_handler' => Frontend\AjaxHandler::class,
            'sidebar_ajax_handler' => Frontend\SidebarAjaxHandler::class,
            'view_tracker' => Frontend\PropertyViewTracker::class,
            'card_renderer' => Frontend\PropertyCardRenderer::class,
            'single_renderer' => Frontend\PropertySingleRenderer::class,
            'layout_manager' => Frontend\LayoutManager::class,
        ];
        
        return isset($legacy_map[$name]) && isset($this->services[$legacy_map[$name]]);
    }
}

/**
 * Legacy instantiation for backward compatibility
 */
if (!function_exists('hvnly_frontend_init')) {
    function hvnly_frontend_init() {
        return Frontend::get_instance();
    }
}

// Initialize frontend
if (!defined('HVNLY_FRONTEND_INITIALIZED')) {
    define('HVNLY_FRONTEND_INITIALIZED', true);
}