<?php
namespace Tiamr\Frontend;

use Tiamr\Rules\Free_Rule_Evaluator;
use Tiamr\Rules\User_Context;

if (!defined('ABSPATH')) {
    exit;
}


final class Menu_Filter {
    /** @var Free_Rule_Evaluator */
    private $free_rule_evaluator;

    /** @var User_Context */
    private $user_context;

    public function __construct(Free_Rule_Evaluator $free_rule_evaluator, User_Context $user_context) {
        $this->free_rule_evaluator = $free_rule_evaluator;
        $this->user_context        = $user_context;

        // Run late so other menu plugins can remove their items first. We never re-add anything.
        add_filter('wp_nav_menu_objects', [$this, 'filter_menu_items'], 100, 2);
    }

    /**
     * @param array<int, \WP_Post> $items
     * @param object               $args
     * @return array<int, \WP_Post>
     */
    public function filter_menu_items(array $items, $args): array {
        if (empty($items)) {
            return $items;
        }

        $hidden_ids = [];
        $visible_items = [];

        foreach ($items as $item) {
            if (!$item instanceof \WP_Post) {
                $visible_items[] = $item;
                continue;
            }

            $parent_id = isset($item->menu_item_parent) ? (int) $item->menu_item_parent : 0;

            if ($parent_id > 0 && in_array($parent_id, $hidden_ids, true)) {
                $hidden_ids[] = (int) $item->ID;
                continue;
            }

            $visible = $this->free_rule_evaluator->is_item_visible($item);

            /**
             * Allows a future Pro add-on to extend or override the visibility result.
             *
             * Pro should return the Free result unchanged when no Pro rule exists for
             * the item, and should never re-add items removed by other plugins.
             */
            $visible = (bool) apply_filters(
                'tiamr/menu_item_is_visible',
                $visible,
                $item,
                $this->user_context,
                $args
            );

            if (!$visible) {
                $hidden_ids[] = (int) $item->ID;
                continue;
            }

            $visible_items[] = $item;
        }

        return $visible_items;
    }
}
