<?php
/**
 * Woostify Theme Builder Nav Menu
 *
 * @package Woostify Pro
 */

if ( ! class_exists( 'Woostify_Custom_Nav_Walker' ) ) {

	/**
	 * Woostify custom navigation walker.
	 *
	 */
	class Woostify_Custom_Nav_Walker extends Walker_Nav_Menu {

        /**
		 * Menu item ID.
		 *
		 * @var int
		 */
		private $menu_megamenu_item_id = 0;

        /**
		 * Parse post meta of particular passed key & return its value.
		 *
		 * @param array  $post_meta Post meta of megamenu.
		 * @param string $key Meta item key.
		 *
		 * @return mixed value of meta key.
		 */
		public function get_post_meta( $post_meta, $key ) {
			return isset( $post_meta[ $key ][0] ) ? $post_meta[ $key ][0] : '';
		}

		/**
		 * Starts the list before the elements are added.
		 *
		 * @param string $output Passed by reference. Used to append additional content.
		 * @param int    $depth  Depth of menu item. Used for padding.
		 * @param array  $args   An array of arguments. @see wp_nav_menu().
		 */
		public function start_lvl( &$output, $depth = 0, $args = array() ) {
			$indent = str_repeat( "\t", $depth );

			if ( 0 === $depth ) {
				if ( ! empty( $this->megamenu_enable ) && 'off' !== $this->megamenu_enable ) {
					// Adding "hidden" class to fix the visibility issue during page load.
					$output .= "\n$indent<ul class=\"woostify-megamenu sub-menu woostify-mega-menu-width-content\">\n";
				} elseif ( ! empty( $this->legacy_width ) ) {
					$output .= "\n$indent<ul class=\"sub-menu sub-mega-menu\">\n";
					$output .= "$indent<div class=\"mega-menu-wrapper\">\n";
				} else {
					$output .= "\n$indent<ul class=\"sub-menu\">\n";
				}
			} elseif ( 2 <= $depth && ! empty( $this->megamenu_enable ) && 'off' !== $this->megamenu_enable ) {
				$output .= "\n$indent<ul class='woostify-nested-sub-menu sub-menu'\">\n";
			} else {
				$output .= "\n$indent<ul class=\"sub-menu\">\n";
			}
		}

		/**
		 * Ends the list of after the elements are added.
		 *
		 * @param string   $output Passed by reference. Used to append additional content.
		 * @param int      $depth  Depth of menu item. Used for padding.
		 * @param array    $args   An array of arguments. @see wp_nav_menu().
		 */
		public function end_lvl( &$output, $depth = 0, $args = array() ) {
			$indent  = str_repeat( "\t", $depth );
			if ( 0 === $depth && ( empty( $this->megamenu_enable ) || 'off' === $this->megamenu_enable ) && ! empty( $this->legacy_width ) ) {
				$output .= "$indent</div>\n";
			}
			$output .= "$indent</ul>\n";
		}

        /**
		 * Modified the menu output.
		 *
		 * @param string $output Passed by reference. Used to append additional content.
		 * @param object $item   Menu item data object.
		 * @param int    $depth  Depth of menu item. Used for padding.
		 * @param array  $args   An array of arguments. @see wp_nav_menu().
		 * @param int    $id     Current item ID.
		 */
		public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {

			$indent    = ( $depth ) ? str_repeat( "\t", $depth ) : '';
			$post_meta = get_post_meta( $item->ID );
			
			if ( 0 === $depth ) {
                $this->megamenu_enable = isset( $item->megamenu_enable ) && ! empty( $item->megamenu_enable ) ? $item->megamenu_enable : get_post_meta( $item->ID, 'woostify_menu_item_megamenu_enable', true );
                $this->megamenu_width  = isset( $item->megamenu_width ) && ! empty( $item->megamenu_width ) ? $item->megamenu_width : get_post_meta( $item->ID, 'woostify_menu_item_megamenu_settings_width', true );

                $this->legacy_width = get_post_meta( $item->ID, 'woostify_mega_menu_item_width', true );
                $this->legacy_pos   = get_post_meta( $item->ID, 'woostify_mega_menu_item_position', true );
                $this->legacy_icon  = get_post_meta( $item->ID, 'woostify_mega_menu_item_icon', true );

                $this->menu_megamenu_item_id = $item->ID;
            } else {
				// Reset properties if not a depth 0 item to ensure correct behavior.
				// But we often need the parent settings. 
				// Actually, the walker keeps the state from the last Depth 0 call.
			}

            $this->menu_megamenu_individual_item_id = $item->ID;

            $class_names = '';

			$classes   = empty( $item->classes ) ? array() : (array) $item->classes;
			$classes[] = 'menu-item-' . $item->ID;

			// Mega menu detection.
			$is_theme_builder_mega = ( ! empty( $this->megamenu_enable ) && 'off' !== $this->megamenu_enable );
			$is_legacy_mega        = ! empty( $this->legacy_width ) || 'mega_menu' === $item->object;

			// Mega menu and Hide headings classes.
			if ( 0 === $depth ) {
				if ( $is_theme_builder_mega ) {
					$classes[] = 'menu-item-has-children woostify-megamenu-li ' . $this->megamenu_width . '-width-mega';
				} elseif ( $is_legacy_mega ) {
					$classes[] = 'menu-item-has-children';
					$classes[] = 'menu-item-has-mega-menu';
					// Fallback to content-width if legacy_width is missing but object is mega_menu.
					$l_width = ! empty( $this->legacy_width ) ? $this->legacy_width : 'content-width';
					if ( strpos( $l_width, 'width' ) === false ) { $l_width .= '-width'; }
					$classes[] = 'has-mega-menu-' . $l_width;
					if ( ! empty( $this->legacy_pos ) ) {
						$classes[] = 'megamenu-position-' . $this->legacy_pos;
					}
				}
			}

			/**
			 * Filters the arguments for a single nav menu item.
			 *
			 * @since 4.4.0
			 *
			 * @param stdClass $args  An object of wp_nav_menu() arguments.
			 * @param WP_Post  $item  Menu item data object.
			 * @param int      $depth Depth of menu item. Used for padding.
			 */
			$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );

            /**
			 * Filters the CSS class(es) applied to a menu item's list item element.
			 *
			 * @since 3.0.0
			 * @since 4.1.0 The `$depth` parameter was added.
			 *
			 * @param array    $classes The CSS classes that are applied to the menu item's `<li>` element.
			 * @param WP_Post  $item    The current menu item.
			 * @param stdClass $args    An object of wp_nav_menu() arguments.
			 * @param int      $depth   Depth of menu item. Used for padding.
			 */
			$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
			$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';

            /**
			 * Filters the ID applied to a menu item's list item element.
			 *
			 * @since 3.0.1
			 * @since 4.1.0 The `$depth` parameter was added.
			 *
			 * @param string   $menu_id The ID that is applied to the menu item's `<li>` element.
			 * @param WP_Post  $item    The current menu item.
			 * @param stdClass $args    An object of wp_nav_menu() arguments.
			 * @param int      $depth   Depth of menu item. Used for padding.
			 */
			$id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth );

			$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';

			$output .= $indent . '<li' . $id . $class_names . '>';

            $atts           = array();
			$atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
			$atts['target'] = ! empty( $item->target ) ? $item->target : '';
			$atts['rel']    = ! empty( $item->xfn ) ? $item->xfn : '';
			$atts['href']   = ! empty( $item->url ) ? $item->url : '';

            $item_output  = $args->before;

			$link_classes = array('menu-link');
			if ( 'on' === $item->megamenu_disable_label ) {
				$link_classes[] = 'woostify-hide-menu-item';
			}

			$link_classes_str = join( ' ', $link_classes );

			$atts['class'] = ! empty( $link_classes_str ) ? $link_classes_str : '';

            /**
			 * Filters the HTML attributes applied to a menu item's anchor element.
			 *
			 * @since 3.6.0
			 * @since 4.1.0 The `$depth` parameter was added.
			 *
			 * @param array $atts {
			 *     The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
			 *
			 *     @type string $title  Title attribute.
			 *     @type string $target Target attribute.
			 *     @type string $rel    The rel attribute.
			 *     @type string $href   The href attribute.
			 * }
			 * @param WP_Post  $item  The current menu item.
			 * @param stdClass $args  An object of wp_nav_menu() arguments.
			 * @param int      $depth Depth of menu item. Used for padding.
			 */
			$atts       = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
			$attributes = '';
            foreach ( $atts as $attr => $value ) {
				if ( ! empty( $value ) ) {
					$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );

					if ( 'class' !== $attr ) {
						$attributes .= ' ' . $attr . '="' . $value . '"';
					}
				}
			}

            /** This filter is documented in wp-includes/post-template.php */
            $title = apply_filters( 'the_title', $item->title, $item->ID );
            /**
			 * Filters a menu item's title.
			 *
			 * @since 4.4.0
			 *
			 * @param string   $title The menu item's title.
			 * @param WP_Post  $item  The current menu item.
			 * @param stdClass $args  An object of wp_nav_menu() arguments.
			 * @param int      $depth Depth of menu item. Used for padding.
			 */
			$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );

			// Check this item has children.
			$has_child = in_array( 'menu-item-has-children', $classes, true ) ? true : false;

			// Wrap menu text in a span tag.
			$title = '<span class="menu-text">' . $title . '</span>';

            $item_output .= '<a' . $attributes . ' class="' . $atts['class'] . '" data-menu-item-id="'.$item->ID.'">';

            $item_output     .= $args->link_before . $title . $args->link_after;

			// Add arrow icon.
			if ( $has_child || ( 0 === $depth && ( $is_theme_builder_mega || $is_legacy_mega ) ) ) {
				$item_output .= '<span class="menu-item-arrow arrow-icon">' . Woostify_Icon::fetch_svg_icon( 'angle-down', false ) . '</span>';
			}

            $item_output .= '</a>';

			// Add menu arrow button.
			if ( ( $has_child || ( 0 === $depth && $is_theme_builder_mega ) ) && $is_theme_builder_mega ) {
				$button_classes     = array( 'woostify-menu-toggle', 'menu-link' );
				$button_classes_str = join( ' ', $button_classes );
				$item_output       .= '<button class="' . $button_classes_str . '"><span class="menu-item-arrow arrow-icon">' . Woostify_Icon::fetch_svg_icon( 'angle-down', false ) . '</span></button>';
			}

			$content = '';

            if ( $is_theme_builder_mega && isset( $item->megamenu_content_src ) && 'default' != $item->megamenu_content_src ) {
				
				ob_start();

                switch ( $item->megamenu_content_src ) {

					case 'template':
						// Get ID.
						$template_id = $item->megamenu_template_id;

						// Get template content.
						if ( ! empty( $template_id ) ) {
							$Woostify_Builder_Nav_Menu = Woostify_Builder_Nav_Menu::get_instance();
							ob_start();
							$Woostify_Builder_Nav_Menu->get_active_page_builder( $template_id );
							$template_content = ob_get_clean();

							if ( ! empty( $template_content ) ) {
								$content .= '<div class="woostify-megamenu sub-menu woostify-mega-menu-width-content woostify-mm-custom-content woostify-mm-template-content" data-template-id="' . $template_id . '">';
								$content .= $template_content;
								$content .= '</div>';
							}
						}

						break;

					case 'custom_text':
						$content  = '<div class="woostify-megamenu sub-menu woostify-mega-menu-width-content woostify-mm-custom-content woostify-mm-custom-text-content">';
						$content .= do_shortcode( $item->megamenu_custom_text );
						$content .= '</div>';

						break;

                    default:
						// code...
						break;
				}
				
                ob_end_clean();

				$item_output .= $content;
			
            } elseif ( $is_legacy_mega ) {
				// Render legacy mega menu content.
				$mega_menu_id = $item->object_id;
				if ( ! empty( $mega_menu_id ) && 'mega_menu' === $item->object ) {
					ob_start();
					if ( is_elementor_activated( $mega_menu_id ) ) {
						echo \Elementor\Plugin::instance()->frontend->get_builder_content_for_display( $mega_menu_id );
					} else {
						$mega_post = get_post( $mega_menu_id );
						if ( $mega_post ) {
							echo do_shortcode( $mega_post->post_content );
						}
					}
					$legacy_content = ob_get_clean();

					if ( ! empty( $legacy_content ) ) {
						$content  = '<ul class="sub-mega-menu">';
						$content  .= '<div class="mega-menu-wrapper">';
						$content .= $legacy_content;
						$content .= '</div>';
						$content .= '</ul>';
						$item_output .= $content;
					}
				}
			}
			
            $item_output .= $args->after;

            /**
			 * Filters a menu item's starting output.
			 *
			 * The menu item's starting output only includes `$args->before`, the opening `<a>`,
			 * the menu item's title, the closing `</a>`, and `$args->after`. Currently, there is
			 * no filter for modifying the opening and closing `<li>` for a menu item.
			 *
			 * @since 3.0.0
			 *
			 * @param string   $item_output The menu item's starting HTML output.
			 * @param WP_Post  $item        Menu item data object.
			 * @param int      $depth       Depth of menu item. Used for padding.
			 * @param stdClass $args        An object of wp_nav_menu() arguments.
			 */
			$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

        }

    }
}