<?php
/**
 * AR Display
 * https://augmentedrealityplugins.com
**/

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

if ( ! function_exists( 'ar_get_gallery_image_dimensions' ) ) {
	/**
	 * Pixel dimensions for ar-gallery.php query string (matches user-upload URL pattern).
	 *
	 * @param string|int $thumbnail_id Attachment ID, or empty.
	 * @param string     $image_url    Full image URL for url= gallery links.
	 * @return int[] { width, height }; zeros if unknown.
	 */
	function ar_get_gallery_image_dimensions( $thumbnail_id, $image_url = '' ) {
		$thumbnail_id = (string) $thumbnail_id;
		$image_url    = (string) $image_url;

		if ( $thumbnail_id !== '' && is_numeric( $thumbnail_id ) ) {
			$aid  = (int) $thumbnail_id;
			$meta = wp_get_attachment_metadata( $aid );
			if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
				return array( (int) $meta['width'], (int) $meta['height'] );
			}
			$src = wp_get_attachment_image_src( $aid, 'full' );
			if ( $src && ! empty( $src[1] ) && ! empty( $src[2] ) ) {
				return array( (int) $src[1], (int) $src[2] );
			}
		}

		if ( $image_url !== '' ) {
			$att_id = attachment_url_to_postid( $image_url );
			if ( $att_id ) {
				$meta = wp_get_attachment_metadata( $att_id );
				if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
					return array( (int) $meta['width'], (int) $meta['height'] );
				}
			}

			$upload_dir = wp_upload_dir();
			if ( ! empty( $upload_dir['baseurl'] ) && ! empty( $upload_dir['basedir'] )
				&& strpos( $image_url, $upload_dir['baseurl'] ) === 0 ) {
				$rel = substr( $image_url, strlen( $upload_dir['baseurl'] ) );
				if ( $rel !== false ) {
					$path = wp_normalize_path( $upload_dir['basedir'] . $rel );
					if ( $path && file_exists( $path ) && is_readable( $path ) ) {
						$size = @getimagesize( $path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
						if ( $size && isset( $size[0], $size[1] ) && $size[0] > 0 && $size[1] > 0 ) {
							return array( (int) $size[0], (int) $size[1] );
						}
					}
				}
			}
		}

		return array( 0, 0 );
	}
}

/******* Element Positions *******/
$ar_css_names = array ('AR Button'=> '.ar-button', 'Dimensions'=>'.dimension', 'Fullscreen Button'=>'.ar_popup-btn', 'QR Code'=>'.ar-qrcode', 'Thumbnail Slides'=>'.ar_slider', 'Play/Pause'=>'.ar-button-animation', 'Reset Button'=>'.ar-reset', 'Call To Action'=>'.ar_cta_button', 'Model Variants'=>'.ar-variant-container');
$ar_css_styles = array();
$ar_css_styles['Top Left'] = 'top: 6px !important; bottom: auto !important; left: 6px !important; right: auto !important; margin: 0 !important;';
$ar_css_styles['Top Center'] = 'top: 6px !important; bottom: auto !important; margin: 0 auto !important; left: 0 !important; right: 0 !important;';
$ar_css_styles['Top Right'] = 'top: 6px !important; bottom: auto !important; left: auto !important; right: 6px !important; margin: 0 !important;';
$ar_css_styles['Bottom Left'] = 'top: auto !important; bottom: 6px !important; left: 6px !important; right: auto !important; margin: 0 !important;';
$ar_css_styles['Bottom Center'] = 'top: auto !important; bottom: 6px !important; margin: 0 auto !important; left: 0 !important; right: 0 !important;';
$ar_css_styles['Bottom Right'] = 'top: auto !important; bottom: 6px !important; left: auto !important; right: 6px !important; margin: 0 !important;';

if ( ! class_exists( 'AR_Plugin' ) ) {
    class AR_Plugin {
    
        /**
         * Constructor
         */
        public $ar_model_html;
    
        public function __construct() {
            // Add any necessary hooks or filters here.
            $this->ar_model_html = '';
        }
    
        /**
         * Initialize the plugin.
         */
        public function run() {
            add_shortcode( 'ardisplay', [ $this, 'ar_display_shortcode' ] );
            add_shortcode( 'ar-display', [ $this, 'ar_display_shortcode' ] );
            add_shortcode( 'ar-view', [ $this, 'ar_view_shortcode' ] );
            add_shortcode('ar-qr', [ $this, 'ar_qrcode_shortcode' ]);
            add_shortcode('ar-gallery', [ $this, 'ar_gallery_shortcode' ]);
            add_shortcode('ar-user-upload', [ $this, 'ar_user_upload' ]);
        }
    
        
        public function ar_display_shortcode($atts, $variation_id='') {
            global $ar_plugin_id, $ar_wc_active, $ar_wp_active;
            $model_count = ar_model_count();
    
            $atts = $this->sanitize_atts($atts);
    
            $suffix = $variation_id ? "_var_".$variation_id : '';
    
            //Check if on a mobile and it supports AR.
            extract(get_screen_type());
    
            if ((get_option('ar_licence_valid')=='Valid')OR($model_count<=1)){
                
                if ((!is_array($atts)) OR (!isset($atts['id']))) {
                    $atts['id'] = get_the_ID(); // Use the current post ID if none set
                }
    
                // Check if a glb file exists
                $glb_file = get_post_meta($atts['id'], '_glb_file'.$suffix, true);
    
    
                
                if (!$glb_file && !is_admin()) { // If glb file is not found for the main product
                    $arpost = get_post($atts['id']);
                    if (isset($arpost->post_type) && $arpost->post_type === 'product') { // Ensure it's a product
                        $product = wc_get_product($atts['id']); // Get the WooCommerce product object
                        
                        if ($product && $product->is_type('variable')) { // Check if the product is a variable product
                            $available_variations = $product->get_children(); // Get all variation IDs
                
                            foreach ($available_variations as $variation_id) {
                                $suffix = "_var_" . $variation_id;
                                // Check if the variation has the '_glb_file' meta
                                $variation_glb_file = get_post_meta($variation_id, '_glb_file' . $suffix, true);
                                
                                if ($variation_glb_file) {
                                    $glb_file = ar_get_secure_model_url($variation_glb_file); // If found, set the glb file
                                    $atts['id'] = $variation_id;
                                    break; // Exit the loop as we found a valid glb file
                                }
                            }
                        } elseif ($arpost->post_type === 'product_variation') { // Check if it's a product variation
                            $suffix = "_var_" . $atts['id'];
                            $glb_file = ar_get_secure_model_url(get_post_meta($atts['id'], '_glb_file' . $suffix, true));
                        }
                    }
                }
                
                // If $glb_file is still empty or not found, you can handle the case here, e.g., return a default value or an error message.
                if (!$glb_file) {
                    // Display an empty Model Viewer
                   // return;
                } 
                $model_array=array();
                $ar_model = new AR_Model($atts, $variation_id);
                $model_array = $ar_model->model_array;
    
                $model_array['ar_model_atts']=$atts;
                 
                $alt_output = '';
                
                if ($ar_alternative_id = get_post_meta($atts['id'], '_ar_alternative_id', true )){                
                    if(($isMob) OR ($isTab) OR ($isIPhone) OR ($isIPad) OR ($isAndroid)){  
                        $alt_output = $this->ar_alternative_model($ar_alternative_id, $suffix);
                    }
                }
    
                
                
                $output = $this->ar_display_model_viewer($model_array);
                $output = $output.$alt_output;
                $output .= $this->ar_display_popup($model_array);
                
                //}
            }else{
                //Invalid Licence
                if ($ar_plugin_id=='ar-for-wordpress'){
                    $output = '<a href="/wp-admin/edit.php?post_type=armodels&page">';
                }else{
                    $output = '<a href="/wp-admin/admin.php?page=wc-settings&tab=ar_display">';
                }
                $output .= '<b>'.ar_output('AR Display Limits Exceeded', $ar_plugin_id ).'</b><br>';
                $output .= ar_output('Check Settings', $ar_plugin_id ).'</a> - <a href="https://augmentedrealityplugins.com" target="_blank">'.ar_output('Sign Up for Premium', $ar_plugin_id ).'</a>';
                
            }
            return $output;
        }
    
        /* AR Popup/fullscreen model display */
        public function ar_display_popup($model_array){
    
            $suffix = $model_array['variation_id'] ? "_var_".$model_array['variation_id'] : '';
    
            $ar_model_id = $model_array['model_id'];
            if (strpos($ar_model_id, ',') !== false) {
                $ar_model_id_array = explode(',', $ar_model_id);
                $ar_model_id = str_replace(" ","",implode("_",$ar_model_id_array));
            }
            $model_array['instance_id'] = wp_unique_id('ar_instance_');
            //Fullscreen option - if not disabled in settings
            if ((!isset($model_array['ar_hide_fullscreen']))OR($model_array['ar_hide_fullscreen']=='')){
                $model_array['ar_pop']='pop';
                $model_array['skybox_file'] = get_post_meta($model_array['id'], '_skybox_file'.$suffix, true );
                $popup_output ='
                <div id="ar_popup_'.$ar_model_id.'" class="ar_popup">
                    <div class="ar_popup-content">
                        '.$this->ar_display_model_viewer($model_array, $model_array['model_id']).'
                    </div>
                </div>';
    
                add_action( 'wp_footer', function( $arg ) use ( $popup_output,$model_array,$ar_model_id ) {
                    global $ar_plugin_id;
                    echo wp_kses($popup_output, ar_allowed_html());
                    ?>
                    <script>  
                        jQuery(document).ready(function(){       
                            var options = {                                                   
                                ar_x: <?php echo $model_array['ar_x'] ? esc_html($model_array['ar_x']) : "''";?>,
                                ar_y: <?php echo $model_array['ar_y'] ? esc_html($model_array['ar_y']) : "''";?>,
                                ar_z: <?php echo $model_array['ar_z'] ? esc_html($model_array['ar_z']) : "''";?>,
                                ar_pop: '<?php echo esc_html($model_array['ar_pop']);?>',
                                ar_dimensions_units: '<?php echo esc_html($model_array['ar_dimensions_units']);?>',
                                ar_hide_fullscreen: 'false',
                                ar_model_list: <?php echo count($model_array['ar_model_list']);?>,
                                ar_variants: '<?php echo esc_html($model_array['ar_variants']); ?>',
                                id: '<?php echo esc_html($ar_model_id);?>',
                                instanceId: '<?php echo esc_js($model_array['instance_id']); ?>',
                                pluginId: '<?php echo esc_js( $ar_plugin_id ? $ar_plugin_id : 'ar-for-wordpress' ); ?>'
                            };
                            
                            var model_<?php echo esc_html($ar_model_id);?>_pop = ARModelViewer('<?php echo esc_html($ar_model_id);?>_pop',options);
                        });
    
                    </script>
                    <?php
                } );
                add_action( 'admin_footer', function( $arg ) use ( $popup_output,$model_array,$ar_model_id ) {
                    global $ar_plugin_id;
                    echo wp_kses($popup_output, ar_allowed_html());
                    ?>
                    <script> 
                        jQuery(document).ready(function(){         
                            var options = {                                                   
                                ar_x: <?php echo $model_array['ar_x'] ? esc_html($model_array['ar_x']) : "''";?>,
                                ar_y: <?php echo $model_array['ar_y'] ? esc_html($model_array['ar_y']) : "''";?>,
                                ar_z: <?php echo $model_array['ar_z'] ? esc_html($model_array['ar_z']) : "''";?>,
                                ar_pop: '<?php echo esc_html($model_array['ar_pop']);?>',
                                ar_dimensions_units: '<?php echo esc_html($model_array['ar_dimensions_units']);?>',
                                ar_hide_fullscreen: <?php echo $model_array['ar_hide_fullscreen'] ? 'true' : 'false';?>,
                                ar_model_list: <?php echo count($model_array['ar_model_list']);?>,
                                ar_variants: '<?php echo esc_html($model_array['ar_variants']); ?>',
                                id: '<?php echo esc_html($ar_model_id);?>',
                                instanceId: '<?php echo esc_js($model_array['instance_id']); ?>',
                                pluginId: '<?php echo esc_js( $ar_plugin_id ? $ar_plugin_id : 'ar-for-wordpress' ); ?>'
                            };
                            
                            var model_<?php echo esc_html($ar_model_id);?>_pop = ARModelViewer('<?php echo esc_html($ar_model_id);?>_pop',options);
                        });
    
                    </script>
                    <?php
                } );
            }
        }
        /*Populate Size selector on gallery models*/
        public function read_json_and_populate_gallery_selector($model_array, $aspect_ratio, $orientation, $framed, $frame_color, $wpnonce, $thumbnail_id, $url, $opacity = '1.0', $lock_ratio = false) {
            global $ar_plugin_id;
            // Normalize orientation for query-string output (user expects l/p, not "landscape"/"portrait").
            // `ar-gallery.php` ultimately expects single-letter (l/p) or can infer from pixels.
            $orientation = (string) $orientation;
            if ($orientation === 'landscape') {
                $orientation = 'l';
            } elseif ($orientation === 'portrait') {
                $orientation = 'p';
            } elseif ($orientation === 'square') {
                $orientation = 'square';
            } else {
                $orientation = substr($orientation, 0, 1);
            }

            // Normalize ratio to string (models.json keys are strings).
            $aspect_ratio = (string) $aspect_ratio;
            // Path to the JSON file (read from filesystem to avoid SSL issues)
            $json_file_fs = plugin_dir_path(__FILE__) . '../assets/models/models.json';
            
            // Read the JSON file contents from filesystem
            if (!file_exists($json_file_fs)) {
                echo "Something went wrong: models.json file not found";
                return $model_array;
            }
            
            $json_data = file_get_contents($json_file_fs);
            if ($json_data === false) {
                echo "Something went wrong: Failed to read models.json file";
                return $model_array;
            }
            
            // Decode JSON data into a PHP array
            $data_array = json_decode($json_data, true);
            
            if ($data_array === null || json_last_error() !== JSON_ERROR_NONE) {
                echo "Something went wrong: Error decoding models.json - " . json_last_error_msg();
                return $model_array;
            }
            //var_dump($data_array);die();
            
            // Filter data array by enabled ratios and sizes from settings
            $data_array = ar_filter_gallery_data_by_settings($data_array);
            
            // Check if the ratio exists in the data array
            if (!isset($data_array[$aspect_ratio])) {
                // Get the available ratios from the data array
                $available_ratios = array_keys($data_array);
                // Find the closest ratio
                $aspect_ratio = ar_findClosestRatio($aspect_ratio, $available_ratios);
            }
            $dims_suffix = '';
            if ( ! $lock_ratio && function_exists( 'ar_get_gallery_image_dimensions' ) ) {
                if ( isset( $url ) && $url !== '' ) {
                    list( $gw, $gh ) = ar_get_gallery_image_dimensions( '', $url );
                } else {
                    list( $gw, $gh ) = ar_get_gallery_image_dimensions( $thumbnail_id, '' );
                }
                if ( $gw > 0 && $gh > 0 ) {
                    $dims_suffix = '&width=' . $gw . '&height=' . $gh;
                }
            }

            // Populate the model link. Keep ratio + orientation options in URL (user-configurable),
            // but ensure `o` is single-letter (l/p) and URL is properly encoded.
            if((isset($url))&&($url!='')){
                $model_link = site_url('/wp-content/plugins/'.$ar_plugin_id.'/includes/ar-gallery.php?url=' . rawurlencode($url) . '&ratio=' . $aspect_ratio . '&o=' . $orientation . '&f=' . $framed . '&fc=' . $frame_color . '&opacity=' . $opacity . $dims_suffix . '&_wpnonce=' . $wpnonce);
            }elseif (isset($thumbnail_id)&&($thumbnail_id!='')){
                $model_link = site_url('/wp-content/plugins/'.$ar_plugin_id.'/includes/ar-gallery.php?id=' . $thumbnail_id . '&ratio=' . $aspect_ratio . '&o=' . $orientation . '&f=' . $framed . '&fc=' . $frame_color . '&opacity=' . $opacity . $dims_suffix . '&_wpnonce=' . $wpnonce);
            }
            $model_array['glb_file'] = $model_link;
        
            // Populate the gallery selector
            if (isset($data_array[$aspect_ratio])) {
                    $model_types = $data_array[$aspect_ratio];
                    // Flatten $model_types if needed
                    $flat_model_types = ar_array_flatten($model_types);
                    
                    // Implode after flattening
                    $model_array['ar_gallery_selector'] = implode(',', $flat_model_types);
                } 
            return $model_array;
        }
        /* AR Gallery model display */
        public function ar_gallery_shortcode($atts){
            global $post, $ar_plugin_id;
            $atts = is_array($atts) ? $this->sanitize_atts($atts) : array();
            $post_id = isset($post->ID) ? $post->ID : 0;
            $image_url = '';
            foreach (array('image_url', 'image', 'url') as $image_attr) {
                if (!empty($atts[$image_attr])) {
                    $image_url = esc_url_raw($atts[$image_attr]);
                    break;
                }
            }
            
            // Get the featured image ID
            $thumbnail_id = get_post_thumbnail_id($post_id);
            
            if ($image_url !== '' && function_exists('ar_get_gallery_image_dimensions')) {
                list($width, $height) = ar_get_gallery_image_dimensions('', $image_url);
            } else {
                // Get image metadata
                $image_metadata = wp_get_attachment_metadata($thumbnail_id);
            
                if (!$image_metadata || !isset($image_metadata['width']) || !isset($image_metadata['height'])) {
                    return 'Image metadata not available';
                }
            
                // Get width and height
                $width = $image_metadata['width'];
                $height = $image_metadata['height'];
            }
            
            if ($height == 0) {
                return 'Invalid height';
            }
        
            // Calculate aspect ratio
            // Calculate aspect ratio (always width/height for consistency)
            $raw_ratio = $width / $height;
            $aspect_ratio = round($raw_ratio, 2);
            
            // Determine orientation
            $orientation = 'l'; // default to landscape
            if ($width < $height) {
                $orientation = 'p'; // portrait
                // For portrait images, invert the ratio to match available models
                $aspect_ratio = round($height / $width, 2);
            } elseif ($width == $height) {
                $orientation = 'square'; // square
                $aspect_ratio = 1;
            }
            
            $gallery_ratio_map = array(
                '1:1'    => '1.0',
                '1'      => '1.0',
                '1.0'    => '1.0',
                'a4'     => '1.4142',
                'a3'     => '1.4142',
                'a2'     => '1.4142',
                'a1'     => '1.4142',
                'a4-a1'  => '1.4142',
                '2:3'    => '1.5',
                '1.5'    => '1.5',
                '4:5'    => '1.25',
                '1.25'   => '1.25',
                '3:4'    => '1.33',
                '1.33'   => '1.33',
                '3:1'    => '3.1',
                '3.1'    => '3.1',
            );
            if (isset($atts['ratio'])) {
                $requested_ratio = strtolower(trim($atts['ratio']));
                if (isset($gallery_ratio_map[$requested_ratio])) {
                    $aspect_ratio = $gallery_ratio_map[$requested_ratio];
                }
            }
            if ((string) $aspect_ratio === '1.0') {
                $orientation = 'square';
            }
            
            $orientation_map = array(
                'landscape' => 'l',
                'l'         => 'l',
                'portrait'  => 'p',
                'p'         => 'p',
                'square'    => 'square',
                's'         => 'square',
            );
            if (isset($atts['orientation'])) {
                $requested_orientation = strtolower(trim($atts['orientation']));
                if (isset($orientation_map[$requested_orientation])) {
                    $orientation = $orientation_map[$requested_orientation];
                }
            }
            $lock_gallery_ratio = isset($atts['ratio']) || isset($atts['orientation']);
            
            $requested_scale = '';
            if (isset($atts['scale']) && is_numeric($atts['scale'])) {
                $requested_scale = (string) round((float) $atts['scale'], 2);
            } elseif (isset($atts['size']) && is_numeric($atts['size'])) {
                $requested_scale = (string) round((float) $atts['size'], 2);
            }
            
            $hide_values = array();
            if (isset($atts['hide'])) {
                $hide_values = array_map('trim', explode(',', strtolower($atts['hide'])));
            }
            
            // Initialize the model array and attributes
            $atts_for_model = array();
            $atts_for_model['id'] = !empty($thumbnail_id) ? $thumbnail_id : $post_id;
            $ar_model = new AR_Model($atts_for_model);
            $model_array = $ar_model->model_array;
            $model_array['ar_model_atts'] = $atts;
            $wpnonce = esc_html(wp_create_nonce( 'ar_secure_nonce' ));
            $framed = $model_array['ar_framed'];
            $frame_color = $model_array['ar_frame_color'];
            
            // Get opacity from model_array and ensure it has a valid value
            $opacity = isset($model_array['ar_frame_opacity']) && $model_array['ar_frame_opacity'] !== '' ? $model_array['ar_frame_opacity'] : '1.0';
            
            // Ensure opacity has a valid value (not empty string)
            if (empty($opacity) || $opacity === '') {
                $opacity = '1.0';
            }
            
            $model_array['ar_frame_opacity'] = $opacity;
            if ($lock_gallery_ratio) {
                $model_array['ar_gallery_ratio_locked'] = 1;
            }
    
            //print_r($model_array);die();
    
            // Populate gallery selector using the new function
            $model_array = $this->read_json_and_populate_gallery_selector($model_array, $aspect_ratio, $orientation, $framed, $frame_color, $wpnonce, $image_url !== '' ? '' : $thumbnail_id, $image_url, $opacity, $lock_gallery_ratio);
            
            if ($requested_scale !== '') {
                $model_array['ar_gallery_size'] = $requested_scale;
                $model_array['ar_x'] = $requested_scale;
                $model_array['ar_y'] = $requested_scale;
                $model_array['ar_z'] = $requested_scale;
            }
            
            if (in_array('size', $hide_values, true) || in_array('sizes', $hide_values, true) || in_array('all', $hide_values, true)) {
                $model_array['ar_hide_gallery_sizes'] = 1;
            }
        
            // Generate and return output
            $output = $this->ar_display_model_viewer($model_array);
            $output .= $this->ar_display_popup($model_array);
            
            return $output;
        }        
    
        /************* AR View Short Code Display *******************/
        public function ar_view_shortcode($atts) { 
            global $ar_plugin_id;
            
            $atts = $this->sanitize_atts($atts);
    
            if (get_option('ar_licence_valid')=='Valid'){
                $logo='';
                $ar_button_default='';
                if (get_option('ar_view_file')==''){
                    $logo=esc_url( plugins_url( "assets/images/ar-view-btn.png", dirname(__FILE__) ) );
                    $ar_button_default=' ar-button-default';
                }else{
                    $logo=get_option('ar_view_file');
                }
    
                if ((!isset($atts))||(!isset($atts['id']))){
                    return 'Please include AR model id in shortcode. [ar-view id=X]';
                }else{
                    $mdl_id = $atts['id'];
                    $atts['ar_hide_model']='1';
                    $atts['ar_enable_fullscreen']='1';
                    if (get_option('ar_view_in_ar')){
                        $ar_view_text = get_option('ar_view_in_ar');
                    }else{
                        $ar_view_text =ar_output('View in AR', $ar_plugin_id );
                    }
                    if (get_option('ar_view_in_3d')){
                        $ar_view_text_3d = get_option('ar_view_in_3d');
                    }else{
                        $ar_view_text_3d =ar_output('View in 3D', $ar_plugin_id );
                    }
                    $atts['ar_show_close_on_devices']='1';
                    $ar_not_supported =ar_output('Your device does not support Augmented Reality. You can view the 3D model or scan the QR code with an AR supported mobile device.', $ar_plugin_id );
                    //Check if on a mobile and it supports AR.
                    extract(get_screen_type());
    
                    if(($isMob) OR ($isTab) OR ($isIPhone) OR ($isIPad) OR ($isAndroid)){  
                        //Mobile
                        //If Alternative mobile ID exists then display mobile model if viewing on mobile or tablet
                        if ($mob_id = get_post_meta($atts['id'], '_ar_mobile_id', true )){
                            $atts['id'] = $mob_id;
                        }
    
                        $popup_output = '<div id="arqr_popup_'.$atts['id'].'" class="ar_popup" style="display:none;"><div class="ar_popup-content arqr_popup-content"><div id="ar_qr_'.$atts['id'].'" class=" arqr_popup-container">'.$this->ar_qrcode_shortcode($atts).'<p>'.ar_output('Scan the QR with your device to view in Augmented Reality',$ar_plugin_id).'</p></div><div class="ar-popup-btn-container hide_on_devices"><button id="arqr_close_'.$atts['id'].'_pop" class="ar_popup-btn hide_on_devices"  onclick="document.getElementById(\'arqr_popup_'.$atts['id'].'\').style.display = \'none\';"><img src="'.esc_url( plugins_url( "assets/images/close.png", dirname(__FILE__) ) ).'" class="ar-fullscreen_btn-img"></button></div></div></div>';
                        $fallback = urlencode(get_permalink($atts['id']));
    
                        if ((isset($atts['text']))AND($atts['text']==true)){
                            //Text - Mobile
                            $atts['ar_hide_model']='0';
                            return '<span class="ar_view_text_link '.$ar_button_default.'" id="ar-button-standalone" onclick="document.getElementById(\'ar-button_'.$atts['id'].'\').click()">'.$ar_view_text.'</span> / <span class="ar_view_text_link ar_cursor_pointer '.$ar_button_default.'" id="ar-button-standalone_'.$atts['id'].'" onclick="document.getElementById(\'ardisplay_viewer_'.$atts['id'].'_pop\').classList.remove(\'nodisplay\');document.getElementById(\'ar_popup_'.$atts['id'].'\').style.display = \'block\'; ">'.$ar_view_text_3d.'</span>'.$this->ar_display_shortcode($atts).'<script languange="javascript">document.getElementById(\'model_'.$atts['id'].'\').classList.add(\'nodisplay\');</script>';
    
                        }elseif ((isset($atts['buttons']))AND($atts['buttons']==true)){
                            $atts['ar_hide_model']='0';
    
                            if($isAndroid){
                                $glb_file = get_post_meta($atts['id'], '_glb_file', true );
    
                                if($ar_alternative_id = get_post_meta($mdl_id, '_ar_alternative_id', true )){
                                    
                                    $glb_file = get_post_meta($ar_alternative_id, '_glb_file', true );
                                    if (substr(sanitize_text_field($glb_file),0,7)=='http://'){
                                        $glb_file = 'https://'.substr(sanitize_text_field($glb_file),7);
                                    }
    
                                } else {
                                    if (substr(sanitize_text_field($glb_file),0,7)=='http://'){
                                        $glb_file = 'https://'.substr(sanitize_text_field($glb_file),7);
                                    }
                                }
    
                                $ar_plcmnt  = get_post_meta($atts['id'], '_ar_placement', true );
                               
    
                                $enable_vertical = '';
    
                                if($ar_plcmnt == 'wall'){
                                    $enable_vertical = 'enable_vertical_placement=true&';
                                }
    
                                $arview_btn = '<a class="button ar_button" href="intent://arvr.google.com/scene-viewer/1.0?mode=ar_preferred&'.$enable_vertical.'disable_occlusion=true&file='.$glb_file.'#Intent;scheme=https;package=com.google.ar.core;action=android.intent.action.VIEW;S.browser_fallback_url='.$fallback.';end">'.$ar_view_text.'</a>';
    
                            } else {
                                $arview_btn = '<span class="button ar_button" id="ar-button-standalone" onclick="document.getElementById(\'ar-button_'.$atts['id'].'\').click();">'.$ar_view_text.'</span>';
                            }
                            return $arview_btn.'  <span class="button ar_button ar_cursor_pointer" id="ar-button-standalone_'.$atts['id'].'" onclick="document.getElementById(\'ardisplay_viewer_'.$atts['id'].'_pop\').classList.remove(\'nodisplay\');document.getElementById(\'ar_popup_'.$atts['id'].'\').style.display = \'block\';">'.$ar_view_text_3d.'</span>'.$this->ar_display_shortcode($atts).'<script languange="javascript">document.getElementById(\'model_'.$atts['id'].'\').classList.add(\'nodisplay\'); jQuery(function() { jQuery(\'#ardisplay_viewer_'.$atts['id'].'_pop .ar-popup-btn-container\').removeClass(\'hide_on_devices\'); jQuery(\'#ardisplay_viewer_'.$atts['id'].'_pop  #ar_close_'.$atts['id'].'_pop\').removeClass(\'hide_on_devices\'); });</script>';
                        }else{
                            //AR Logo - Mobile
                            if($isAndroid){
    
                                $glb_file = get_post_meta($atts['id'], '_glb_file', true );
    
                                if (substr(sanitize_text_field($glb_file),0,7)=='http://'){
                                    $glb_file = 'https://'.substr(sanitize_text_field($glb_file),7);
                                }
    
                                $ar_plcmnt  = get_post_meta($atts['id'], '_ar_placement', true );
                               
    
                                $enable_vertical = '';
    
                                if($ar_plcmnt == 'wall'){
                                    $enable_vertical = 'enable_vertical_placement=true&';
                                }
    
                                return $this->ar_display_shortcode($atts).'<a class="ar-button_standalone '.$ar_button_default.'" href="intent://arvr.google.com/scene-viewer/1.0?mode=ar_preferred&'.$enable_vertical.'disable_occlusion=true&file='.$glb_file.'#Intent;scheme=https;package=com.google.ar.core;action=android.intent.action.VIEW;S.browser_fallback_url='.$fallback.';end"><img id="ar-img_'.$atts['id'].'" src="'.$logo.'" class="ar-button-img"></a>';
    
                            } else {
    
                                return $this->ar_display_shortcode($atts).'<span class="ar-button_standalone '.$ar_button_default.'" id="ar-button-standalone" onclick="document.getElementById(\'ar-button_'.$atts['id'].'\').click();"><img id="ar-img_'.$atts['id'].'" src="'.$logo.'" class="ar-button-img"></span>';
                            }
                        }    
                    }else{ 
                        //Desktop
    
                        $atts['ar_hide_model']='0';
                        $atts['ar_qr_large']='1';
                        $popup_output = '<div id="arqr_popup_'.$atts['id'].'" class="ar_popup" style="display:none;"><div class="ar_popup-content arqr_popup-content"><div id="ar_qr_'.$atts['id'].'" class=" arqr_popup-container">'.$this->ar_qrcode_shortcode($atts).'<p>'.ar_output('Scan the QR with your device to view in Augmented Reality',$ar_plugin_id).'</p></div><div class="ar-popup-btn-container hide_on_devices"><button id="arqr_close_'.$atts['id'].'_pop" class="ar_popup-btn hide_on_devices"  onclick="document.getElementById(\'arqr_popup_'.$atts['id'].'\').style.display = \'none\';"><img src="'.esc_url( plugins_url( "assets/images/close.png", dirname(__FILE__) ) ).'" class="ar-fullscreen_btn-img"></button></div></div></div>';
                        if (((isset($atts['text']))AND($atts['text']==true))OR((isset($atts['buttons']))AND($atts['buttons']==true))){
                            add_action( 'wp_footer', function( $arg ) use ( $popup_output ) {
                                //echo wp_kses($popup_output, ar_allowed_html());
                                ar_return_file ($popup_output);
                            } );
                        }
                        if ((isset($atts['text']))AND($atts['text']==true)){
                            //Text  
                            return '<span class="ar_view_text_link ar_cursor_pointer '.$ar_button_default.'" id="ar-button-standalone" onclick="document.getElementById(\'arqr_popup_'.$atts['id'].'\').style.display = \'block\';document.getElementById(\'ar-qrcode\').classList.add(\'ar-qrcode-large\');">'.$ar_view_text.'</span> / 
                           <span class="ar_view_text_link ar_cursor_pointer '.$ar_button_default.'" id="ar-button-standalone_'.$atts['id'].'" onclick="document.getElementById(\'ardisplay_viewer_'.$atts['id'].'_pop\').classList.remove(\'nodisplay\');document.getElementById(\'ar_popup_'.$atts['id'].'\').style.display = \'block\';">'.$ar_view_text_3d.'</span>'.$this->ar_display_shortcode($atts).'<script languange="javascript">document.getElementById(\'model_'.$atts['id'].'\').classList.add(\'nodisplay\');</script>';
    
                        }elseif ((isset($atts['buttons']))AND($atts['buttons']==true)){
                            //Buttons      
                            return '<span class="button ar_button ar_cursor_pointer" id="ar-button-standalone" onclick="document.getElementById(\'arqr_popup_'.$atts['id'].'\').style.display = \'block\';document.getElementById(\'ar-qrcode\').classList.add(\'ar-qrcode-large\');">'.$ar_view_text.'</span> 
                           <span class="button ar_button ar_cursor_pointer" id="ar-button-standalone_'.$atts['id'].'" onclick="document.getElementById(\'ardisplay_viewer_'.$atts['id'].'_pop\').classList.remove(\'nodisplay\');document.getElementById(\'ar_popup_'.$atts['id'].'\').style.display = \'block\';">'.$ar_view_text_3d.'</span>'.$this->ar_display_shortcode($atts).'<script languange="javascript">document.getElementById(\'model_'.$atts['id'].'\').classList.add(\'nodisplay\');</script>';
    
                        }else{
                            //AR Logo
                            return $this->ar_display_shortcode($atts).'<span class="ar-button_standalone ar_cursor_pointer '.$ar_button_default.'" id="ar-button-standalone_'.$atts['id'].'" onclick="document.getElementById(\'ardisplay_viewer_'.$atts['id'].'_pop\').classList.remove(\'nodisplay\');document.getElementById(\'ar_popup_'.$atts['id'].'\').style.display = \'block\';"><img id="ar-img_'.$atts['id'].'" src="'.$logo.'" class="ar-button-img"></span><script languange="javascript">document.getElementById(\'model_'.$atts['id'].'\').classList.add(\'nodisplay\');</script>';
                        }
                    }
                }
            }
        }
    
    
        /************* QR Code Short Code Display *******************/
        public function ar_qrcode_shortcode($atts) { 
            if (get_option('ar_licence_valid')=='Valid'){
                global $wp;
    
                $qr_logo_image=esc_url( plugins_url( "assets/images/app_logo.png", dirname(__FILE__) ) );
                    if (get_option('ar_qr_file')!=''){
                        $qr_logo_image=get_option('ar_qr_file');
                    }
                //Check ar_qr_destination and if ids then pass shortcode ids to ar_qr_code, otherwise use url of parent page 
                $ar_qr_url = home_url( $wp->request );
    
                $ar_qr_destination='';
                if (isset($atts['id'])){
                    //If Alternative mobile ID exists then display mobile model if viewing on mobile or tablet
                    if ($mob_id = get_post_meta($atts['id'], '_ar_mobile_id', true )){
                        //Check if on a mobile and it supports AR.
                        extract(get_screen_type());
    
                        if(($isMob) OR ($isTab) OR ($isIPhone) OR ($isIPad) OR ($isAndroid)){  
                            $atts['id'] = $mob_id;
                        }
                    }
                    $ar_qr_destination=get_post_meta($atts['id'], '_ar_qr_destination_mv', true );
                }
                if ($ar_qr_destination==''){
                    $ar_qr_destination=get_option('ar_qr_destination') ? get_option('ar_qr_destination') : 'parent-page';
                }
                
                if (isset($atts['id'])){
                    if (get_post_meta( $atts['id'], '_ar_qr_destination', true )){
                            $ar_qr_destination=get_post_meta( $atts['id'], '_ar_qr_destination', true ).'"';
                            $ar_qr_url = $ar_qr_destination;
                    }
                }
    
                if ($ar_qr_destination == 'model-viewer'){
                    if (isset($atts['cat'])){
                        $ar_qr_url = get_site_url().'?ar-cat='.$atts['cat'];
                    }elseif (isset($atts['id'])){
                        $ar_qr_url = get_site_url().'?ar-view='.$atts['id'];
                    }
                }
    
                 $ar_attid = 0;
                if (isset($atts['cat'])){
                    $ar_attid = $atts['cat'];
                }elseif (isset($atts['id'])){
                    $ar_attid = $atts['id'];
                }
    
                $ar_qr_image_data = base64_encode(ar_qr_code($qr_logo_image,$ar_attid,$ar_qr_url));
                $ar_qr_large ='';
                if (isset($atts['ar_qr_large'])){
                    $ar_qr_large = 'ar-qrcode-large';
                }
                if ($ar_qr_image_data!=''){
                    return '<button id="ar-qrcode" type="button" class="ar-qrcode_standalone hide_on_devices '.$ar_qr_large.'" onclick="this.classList.toggle(\'ar-qrcode-large\');" style="background-image: url(\'data:image/png;base64,'.$ar_qr_image_data.'\');"></button>';
                }
            }
        }
        
        /************* User Upload 3D Model Viewer Shortcode *******************/
        public function ar_user_upload($atts) { 
            if (get_option('ar_licence_valid') == 'Valid') {
                global $wp, $post, $ar_plugin_id;
                $output = array();
                $model_array = array();
    
                $model_array['ar_hide_dimensions'] = '1'; // Hide dimensions for user upload
                $model_array['model_id'] = 'user_upload';
                $model_array['ar_qr_destination'] = 'parent-page'; // Default to parent page for QR code
                $atts['hotspots_html'] = $this->get_ar_hotspots($model_array);
                $atts['qrcode_html'] = $this->get_ar_qr_html($model_array);
                
                $output=ar_user_upload_wp($atts);
                
                
                return $output;
            }
        }
        
    
    
    
        /*********** Display the AR Model Viewer ***********/
        public function ar_display_model_viewer($model_array, $atts_id=''){
            global $wp, $ar_plugin_id, $ar_whitelabel, $ar_css_names, $ar_css_styles, $model_viewer_js_loaded, $ar_scale_js;
            if (!is_admin()) {
                ar_advance_register_script();
                ar_advance_register_style();
            }
        
            $output = '';
            $model_viewer_js = '';
            $model_id = $model_array['model_id'] ?? '';
            
            $skybox_file = $model_array['skybox_file'] ?? '';
            if ($skybox_file != '') {
                $model_array['skybox_file'] = ' skybox-image="'.$skybox_file.'"';
            }
        
            $poster = get_post_meta($model_id, '_ar_poster', true);
            
            // If no poster is set, try to get the featured image, then fall back to default poster
            if (empty($poster)) {
                $featured_image = get_the_post_thumbnail_url($model_id);
                if (!empty($featured_image)) {
                    $poster = $featured_image;
                } else {
                    // Use default poster image from settings
                    $poster = ar_get_default_poster_image();
                }
            }
            
            $model_array['ar_poster'] = $poster ? $poster.'"' : '';
        
            if (($model_array['ar_pop'] ?? '') == 'pop') {
                $model_array['model_id'] .= '_pop';
            }
        
            $model_array['ar_resizing'] = (($model_array['ar_resizing'] ?? '') == 1) ? ' ar-scale="fixed"' : '';
            $model_array['ar_scene_viewer'] = ($model_array['ar_scene_viewer'] ?? '') == 1 ? 'scene-viewer webxr quick-look' : 'webxr scene-viewer quick-look';
        
            if (($model_array['ar_animation_selection'] ?? '') != '') {
                $model_array['ar_scene_viewer'] = 'webxr scene-viewer quick-look';
            }

            // Gallery-builder models are served as dynamic glTF (via ar-gallery.php).
            // Scene Viewer expects a direct .glb URL (intent://arvr.google.com/scene-viewer) and will often
            // open a separate viewer app that cannot load this dynamic glTF URL ("couldn't load object").
            // Force WebXR-only for these models so they stay in-browser like the user-upload flow.
            if ( ! empty( $model_array['glb_file'] ) && is_string( $model_array['glb_file'] ) && strpos( $model_array['glb_file'], 'ar-gallery.php' ) !== false ) {
                $model_array['ar_scene_viewer'] = 'webxr';
            }
        
            if (($model_array['ar_hide_arview'] ?? '') != '') {
                $model_array['ar_hide_arview'] = ' nodisplay';
                $show_ar = '';
            } else {
                $show_ar = ' ar ar-modes="'.$model_array['ar_scene_viewer'].'" ';
            }
        
            if (($model_array['ar_hide_model'] ?? '') != '') {
                $model_array['ar_hide_model'] = ' nodisplay';
                $model_array['ar_hide_arview'] = '';
                $show_ar = ' ar ar-modes="'.$model_array['ar_scene_viewer'].'" ';
            }
        
            $model_array['ar_autoplay'] = ($model_array['ar_autoplay'] ?? '') != '' ? 'autoplay' : '';
            $model_array['ar_disable_zoom'] = ($model_array['ar_disable_zoom'] ?? '') != '' ? 'disable-zoom' : '';
            $model_array['ar_field_of_view'] = ($model_array['ar_field_of_view'] ?? '') != '' ? 'field-of-view="'.$model_array['ar_field_of_view'].'deg"' : 'field-of-view=""';
            $model_array['ar_qr_image'] = $model_array['ar_qr_image'] ?? '';
        
            $min_theta = 'auto';
            $min_pi = 'auto';
            $min_zoom = '20%';
            $max_theta = 'Infinity';
            $max_pi = 'auto';
            $max_zoom = '300';
        
            if (($model_array['ar_zoom_in'] ?? '') != '' && ($model_array['ar_zoom_in'] != 'default')) {
                $model_array['ar_zoom_in'] = 100 - $model_array['ar_zoom_in'];
                $min_zoom = $model_array['ar_zoom_in'].'%"';
            }
        
            if (($model_array['ar_zoom_out'] ?? '') != '' && ($model_array['ar_zoom_out'] != 'default')) {
                $model_array['ar_zoom_out'] = (($model_array['ar_zoom_out'] / 100) * 400) + 100;
                $max_zoom = $model_array['ar_zoom_out'].'%"';
            }
        
            if (($model_array['ar_rotate_limit'] ?? '') != '') {
                $min_pi = $model_array['ar_compass_top_value'] ?? $min_pi;
                $max_pi = $model_array['ar_compass_bottom_value'] ?? $max_pi;
                $min_theta = $model_array['ar_compass_left_value'] ?? $min_theta;
                $max_theta = $model_array['ar_compass_right_value'] ?? $max_theta;
            }
        
            $ar_zoom_out_output = 'min-camera-orbit="'.$min_theta.' '.$min_pi.' '.$min_zoom.'"';
            $ar_zoom_in_output = 'max-camera-orbit="'.$max_theta.' '.$max_pi.' '.$max_zoom.'"';
        
            $model_array['ar_exposure'] = ($model_array['ar_exposure'] ?? '') != '' ? 'exposure="'.$model_array['ar_exposure'].'"' : '';
            $model_array['ar_shadow_intensity'] = ($model_array['ar_shadow_intensity'] ?? '') != '' ? 'shadow-intensity="'.$model_array['ar_shadow_intensity'].'"' : '';
            $model_array['ar_shadow_softness'] = ($model_array['ar_shadow_softness'] ?? '') != '' ? 'shadow-softness="'.$model_array['ar_shadow_softness'].'"' : '';
        
            $ar_camera_orbit = $model_array['ar_camera_orbit'] ?? '';
            $model_array['ar_camera_orbit_reset'] = $ar_camera_orbit;
            $model_array['ar_camera_orbit'] = $ar_camera_orbit ? 'camera-orbit="'.$ar_camera_orbit.'"' : '';
        
            $model_array['ar_environment_image'] = ($model_array['ar_environment_image'] ?? '') != '' ? 'environment-image="legacy"' : '';
            $model_array['ar_emissive'] = ($model_array['ar_emissive'] ?? '') != '' ? ' emissive ' : '';
            $model_array['ar_light_color'] = ($model_array['ar_light_color'] ?? '') != '' ? 'light-color="'.$model_array['ar_light_color'].'"' : '';
        
            global $pagenow;
            $hotspot_js_click = ($pagenow == 'post.php') ? 'onclick="addHotspot()"' : '';
        
            if (($model_viewer_js_loaded != 1) || is_admin()) {
                load_model_viewer_js();
                load_model_viewer_components_js();
                $model_viewer_js_loaded = 1;
            }
        
            extract(get_screen_type());
        
            $server_host = isset($_SERVER['HTTP_HOST']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_HOST'])) : '';
            $server_uri = isset($_SERVER['REQUEST_URI']) ? esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'])) : '';
        
            if (($isFireFox ?? false) || ($isFireFoxiOS ?? false)) {
                if ($isAndroid ?? false) {
                    $output .= '<b>For an optimal Augmented Reality experience it is suggested you use a different browser.</b> <a href="intent://'.$server_host.$server_uri.'#Intent;scheme=https;package=com.android.chrome;end">Please click here to open in Chrome.</a>';
                } elseif ($isIOS ?? false) {
                    $output .= '<b>For an optimal Augmented Reality experience it is suggested you use a different browser such as Safari or <a href="googlechrome://'.$server_host.$server_uri.'">Chrome.</a></b>';
                }
            }
        
            $model_array['play_btn'] = esc_url(!empty($model_array['ar_play_file']) ? $model_array['ar_play_file'] : plugins_url("assets/images/ar-play-btn.png", dirname(__FILE__)));
            $model_array['pause_btn'] = esc_url(!empty($model_array['ar_pause_file']) ? $model_array['ar_pause_file'] : plugins_url("assets/images/ar-pause-btn.png", dirname(__FILE__)));
        
            $play_hide = ($model_array['ar_animation'] ?? false) ? '' : 'display:none;';

            if (empty($model_array['instance_id'])) {
                $model_array['instance_id'] = wp_unique_id('ar_instance_');
            }

            $output .= $this->get_ar_model_html($model_array);
            $ar_qr_image_data = $this->get_ar_qr_html($model_array);
        
            $args = [
                'output' => $output,
                'model_array' => $model_array,
                'ar_qr_image_data' => $ar_qr_image_data,
                'ar_whitelabel' => $ar_whitelabel,
                'show_ar' => $show_ar,
                'ar_zoom_out_output' => $ar_zoom_out_output,
                'ar_zoom_in_output' => $ar_zoom_in_output,
                'hotspot_js_click' => $hotspot_js_click,
                'play_btn' => $model_array['play_btn'],
                'play_hide' => $play_hide,
                'instance_id' => $model_array['instance_id'],
            ];
        
            $this->get_ar_custom_css($model_array);
        
            ob_start();
            $this->load_template('model-viewer', $args);
            return $model_viewer_js.ob_get_clean();
        }
    
    
        public function get_ar_model_html($model_array){
            $output = '';
    
            //$output .= $this->get_ar_qr_html($model_array);
            $output .= $this->get_ar_popup_html($model_array);
            $output .= $this->get_ar_slider_html($model_array);
            $output .= $this->get_ar_hotspots($model_array);
            //$output .= $this->get_ar_custom_css($model_array);
    
            return $output;
        }
    
    
        public function get_ar_qr_html($model_array){
            global $wp;
        
            $output = '';
            $ar_qr_display = ($model_array['ar_hide_qrcode'] ?? '') === '' ? 'block' : 'none';
        
            $qr_logo_image = esc_url( plugins_url( "assets/images/app_logo.png", dirname(__FILE__) ) );
            $ar_wl_logo = get_option('ar_wl_file');
        
            if (!empty($model_array['ar_qr_file'])) {
                $qr_logo_image = $model_array['ar_qr_file'];
            } elseif (!empty($ar_wl_logo)) {
                $qr_logo_image = $ar_wl_logo;
            }
        
            $ar_qr_destination = $model_array['ar_qr_destination_mv'] ?? ($model_array['ar_qr_destination'] ?? '');
            $ar_qr_url = '';

            if ($ar_qr_destination === 'model-viewer') {
                if (!empty($model_array['ar_model_atts']['cat'])) {
                    $ar_qr_url = get_site_url() . '?ar-cat=' . $model_array['ar_model_atts']['cat'];
                } elseif (!empty($model_array['ar_model_atts']['id'])) {
                    if ($mob_id = get_post_meta($model_array['ar_model_atts']['id'], '_ar_mobile_id', true)) {
                        $model_array['ar_model_atts']['id'] = $mob_id;
                    }
                    $ar_qr_url = get_site_url() . '?ar-view=' . $model_array['ar_model_atts']['id'];
                }
            } elseif ($ar_qr_destination === 'parent-page' && !empty($model_array['ar_model_atts'])) {
                $ar_attid = $model_array['ar_model_atts']['cat'] ?? $model_array['ar_model_atts']['id'] ?? null;
                $ar_qr_url = get_permalink(get_the_ID());

                if (!empty($model_array['ar_model_atts']['id']) && get_post_type($model_array['ar_model_atts']['id']) === 'attachment') {
                    $ar_qr_url = home_url($wp->request);
                }
            } else {
                $ar_qr_url = get_permalink(get_the_ID());
            }

            if (!empty($model_array['ar_qr_destination_url'])) {
                $ar_qr_url = $model_array['ar_qr_destination_url'];
            }

            if ($ar_qr_url === '' || $ar_qr_url === false) {
                $ar_qr_url = get_permalink(get_the_ID()) ?: home_url('/');
            }

            $ar_qr_image_data = '';
            if (!empty($model_array['ar_qr_image']) && function_exists('ar_qr_valid_png_data_uri') && ar_qr_valid_png_data_uri($model_array['ar_qr_image'])) {
                $ar_qr_image_data = $model_array['ar_qr_image'];
            }

            if (!function_exists('ar_qr_valid_png_data_uri') || !ar_qr_valid_png_data_uri($ar_qr_image_data)) {
                $id_for_qr = !empty($model_array['ar_model_atts']['id']) ? $model_array['ar_model_atts']['id'] : ($model_array['model_id'] ?? '');
                $png = ar_qr_code($qr_logo_image, $id_for_qr, $ar_qr_url);
                if ($png === '' || $png === false) {
                    $png = ar_qr_code(false, $id_for_qr, $ar_qr_url);
                }
                if ($png === '' || $png === false) {
                    $png = ar_qr_code_api(false, $ar_qr_url);
                }
                $ar_qr_image_data = 'data:image/png;base64,' . base64_encode((string) $png);
            }

            if (function_exists('ar_qr_valid_png_data_uri') && !ar_qr_valid_png_data_uri($ar_qr_image_data)) {
                $png = ar_qr_code_api(false, $ar_qr_url ?: 'https://augmentedrealityplugins.com');
                $ar_qr_image_data = 'data:image/png;base64,' . base64_encode((string) $png);
            }

            return $ar_qr_image_data;
        }
    
    
        public function get_ar_popup_html($model_array) {
            $output = '';
            $atts_id = $model_array['ar_model_atts']['id'] ?? '';
            $ar_model_id = $model_array['model_id'] ?? '';
            $ar_atts_id = $atts_id;
        
            if (strpos($ar_model_id, ',') !== false) {
                $ar_model_id_array = explode(',', $ar_model_id);
                $ar_model_id = str_replace(" ","",implode("_",$ar_model_id_array));
        
                $ar_atts_id_array = explode(',', $ar_atts_id);
                $ar_atts_id = str_replace(" ","",implode("_",$ar_atts_id_array));
            }
        
            if (($model_array['ar_hide_reset'] ?? '') != 1) {
                $output .= '<div class="ar-reset-btn-container">
                    <button id="ar-reset_'.$ar_model_id.'" type="button" class="asasa ar-reset" onclick="document.getElementById(\'model_'.$ar_model_id.'\').setAttribute(\'camera-orbit\', \''.$model_array['ar_camera_orbit_reset'].'\');return getData()"><img src="'.esc_url( plugins_url( "assets/images/reset.png", dirname(__FILE__) ) ).'"></button>
                    </div>';
            }
        
            $ar_show_close_on_devices = ($model_array['ar_show_close_on_devices'] ?? '') === '' ? 'hide_on_devices' : '';
            $output .= '<div class="ar-popup-btn-container '.$ar_show_close_on_devices.'">';
        
            $ar_hide_fullscreen = $model_array['ar_hide_fullscreen'] ?? '';
            if ($ar_hide_fullscreen === '') {
                if (($model_array['ar_pop'] ?? '') == 'pop') {
                    $mdl_id = $atts_id ?: ($model_array['model_id'] ?? '');
                    $output .= '<button id="ar_close_'.$ar_atts_id.'" type="button" class="ar_popup-btn '.$ar_show_close_on_devices.'"><img src="'.esc_url( plugins_url( "assets/images/close.png", dirname(__FILE__) ) ).'" class="ar-fullscreen_btn-img"></button>';
                } else {
                    $ar_fullscreen_image = $model_array['ar_fullscreen_file'] ? $model_array['ar_fullscreen_file'] : esc_url( plugins_url( "assets/images/fullscreen.png", dirname(__FILE__) ) );
                    $output .= '<button id="ar_pop_Btn_'.$ar_model_id.'" type="button" class="ar_popup-btn hide_on_devices"><img src="'.$ar_fullscreen_image.'" class="ar-fullscreen_btn-img"></button>';
                }
            }
        
            $output .= '</div>';
        
            if (!empty($model_array['ar_variants'])) {
                $output .= '<div class="ar-variant-container"><select id="variant_'.$model_array['model_id'].'"></select></div>';
            }
        
            return $output;
        }
        
        public function get_ar_slider_html($model_array) {
            $ar_model_id = $model_array['model_id'] ?? '';
        
            if (strpos($ar_model_id, ',') !== false) {
                $ar_model_id_array = explode(',', $ar_model_id);
                $ar_model_id = str_replace(" ","",implode("_",$ar_model_id_array));
            }
        
            $output = '';
            if (!empty($model_array['ar_model_list'])) {
                $model_array['ar_model_list'] = array_filter($model_array['ar_model_list']);
                $model_array['ar_model_list'] = array_unique($model_array['ar_model_list']);
        
                if (count($model_array['ar_model_list']) > 1) {
                    $open_div = '<div id="ar_slider" class="ar_slider"><div class="ar_slides">';
                    $slide_count = 0;
        
                    foreach ($model_array['ar_model_list'] as $v) {
                        $slide_count++;
                        $slide_selected = ($slide_count == 1) ? 'selected' : '';
                        $suffix = '';
        
                        $arpost = get_post($v);
                        if ($arpost && $arpost->post_type === 'product_variation') {
                            $suffix = "_var_".$v;
                        }
        
                        $glb_file = ar_get_secure_model_url(get_post_meta($v, '_glb_file'.$suffix, true));
                        $poster_meta = get_post_meta($v, '_ar_poster'.$suffix, true);
                        $ar_poster = $poster_meta ? $poster_meta.'"' : get_the_post_thumbnail_url($v);
        
                        if ($glb_file != '') {
                            $output .= '<button id="ar_btn_'.$v.'" class="ar_slide '.$slide_selected.'" onclick="switchSrc(\'model_'.$ar_model_id.'\', this, \''.$glb_file.'\', \''.ar_get_secure_model_url(get_post_meta($v, '_usdz_file'.$suffix, true)).'\')" style="background-image: url(\''.esc_url($ar_poster).'\');"></button>';
                        }
                    }
        
                    $close_div = '</div></div>';
                }
        
                if ($output != '') {
                    $output = $open_div . $output . $close_div;
                }
            }
        
            $output .= '<input type="hidden" id="src_'.$ar_model_id.'" value="'. ar_get_secure_model_url($model_array['glb_file'] ?? '') .'">';
            return $output;
        }
    
    
        public function get_ar_hotspots($model_array){
            global $ar_plugin_id;
        
            $ar_model_id = $model_array['model_id'] ?? '';
        
            if (strpos($ar_model_id, ',') !== false) {
                $ar_model_id_array = explode(',', $ar_model_id);
                $ar_model_id = str_replace(" ","",implode("_",$ar_model_id_array));
            }
        
            $output = '';
        
            $ar_dimensions_display = (($model_array['ar_hide_dimensions'] ?? '') === '') ? '' : ' nodisplay';
            $ar_dimensions_label = (($model_array['ar_hide_dimensions'] ?? '') !== '') ? ($model_array['ar_dimensions_label'] ?? '') : esc_html('Dimensions');
        
            $output .= '
            <button slot="hotspot-dot+X-Y+Z" class="dot nodisplay" data-position="1 -1 1" data-normal="1 0 0"></button>
            <button slot="hotspot-dim+X-Y" class="dimension nodisplay" data-position="1 -1 0" data-normal="1 0 0"></button>
            <button slot="hotspot-dot+X-Y-Z" class="dot nodisplay" data-position="1 -1 -1" data-normal="1 0 0"></button>
            <button slot="hotspot-dim+X-Z" class="dimension nodisplay" data-position="1 0 -1" data-normal="1 0 0"></button>
            <button slot="hotspot-dot+X+Y-Z" class="dot nodisplay" data-position="1 1 -1" data-normal="0 1 0"></button>
            <button slot="hotspot-dim+Y-Z" class="dimension nodisplay" data-position="0 -1 -1" data-normal="0 1 0"></button>
            <button slot="hotspot-dot-X+Y-Z" class="dot nodisplay" data-position="-1 1 -1" data-normal="0 1 0"></button>
            <button slot="hotspot-dim-X-Z" class="dimension nodisplay" data-position="-1 0 -1" data-normal="-1 0 0"></button>
            <button slot="hotspot-dot-X-Y-Z" class="dot nodisplay" data-position="-1 -1 -1" data-normal="-1 0 0"></button>
            <button slot="hotspot-dim-X-Y" class="dimension nodisplay" data-position="-1 -1 0" data-normal="-1 0 0"></button>
            <button slot="hotspot-dot-X-Y+Z" class="dot nodisplay" data-position="-1 -1 1" data-normal="-1 0 0"></button>';
            
            // Only output dimensions control if not hidden
            if (($model_array['ar_hide_dimensions'] ?? '') === '') {
                $output .= '
                <div id="controls" class="dimension ar-dimension-control">
                    <label for="show-dimensions_'.$ar_model_id.'" style="margin:0px !important;">'.$ar_dimensions_label.':</label>
                    <input id="show-dimensions_'.$ar_model_id.'" type="checkbox" style="cursor: pointer;">
                </div>';
            }
        
            return $output;
        }
    
        public function get_ar_custom_css($model_array){
            global $ar_css_names, $ar_css_styles;
            $output = '';
            $css_handle = 'ar-custom-style';
            $css_file_name = 'uploads/ar-custom-styles.css';
        
            if (!empty($model_array['ar_css_override'])) {
                $css_handle .= '_'.($model_array['id'] ?? '');
                $css_file_name = 'uploads/ar-custom-styles_'.($model_array['id'] ?? '').'.css';
            }
        
            if (!empty($model_array['ar_css_positions']) && is_array($model_array['ar_css_positions'])) {
                foreach ($model_array['ar_css_positions'] as $element => $pos) {
                    if (($pos !== 'Default') && !empty($element) && !empty($pos)) {
                        if ($element === 'Dimensions') {
                            $output .= esc_attr($ar_css_names[$element]) . '{' . esc_attr($ar_css_styles[$pos]) . ' transform: translateX(0%) !important; }';
                        } else {
                            $output .= esc_attr($ar_css_names[$element]) . '{' . esc_attr($ar_css_styles[$pos]) . '}';
                        }
                    }
                }
        
                if (!empty($model_array['ar_show_close_on_devices'])) {
                    $output .= '#ar-button_' . esc_html($model_array['model_id'] ?? '') . '_pop{top:40px !important;}';
                }
            }
        
            $ar_progress_bar_color = get_option('ar_progress_bar_color');
            if (!empty($ar_progress_bar_color)) {
                $output .= '/* Custom loading bar style for model-viewer */ 
                model-viewer::part(default-progress-bar) { background-color: '.$ar_progress_bar_color.'; } 
                model-viewer::part(default-progress-bar)::-webkit-progress-bar { background-color: #f0f0f0; } 
                model-viewer::part(default-progress-bar)::-webkit-progress-value { background-color: '.$ar_progress_bar_color.'; } ';
            }
        
            if (!empty($model_array['ar_css']) && ($model_array['ar_pop'] ?? '') !== 'pop') {
                $output .= esc_attr($model_array['ar_css']);
            }
        
            if (($model_array['ar_pop'] ?? '') !== 'pop') {
                if (!function_exists('WP_Filesystem')) {
                    require_once ABSPATH . 'wp-admin/includes/file.php';
                }
        
                global $wp_filesystem;
                $creds = request_filesystem_credentials(site_url());
        
                if (WP_Filesystem($creds) && !empty($wp_filesystem)) {
                    $file_path = WP_CONTENT_DIR . '/' . $css_file_name;
                    $wp_filesystem->put_contents($file_path, $output);
                }
            }
        
            if (file_exists(WP_CONTENT_DIR . '/' . $css_file_name)) {
                $lastmodtime = filemtime(WP_CONTENT_DIR . '/' . $css_file_name);
                wp_enqueue_style($css_handle, content_url($css_file_name), array(), $lastmodtime);
            } else {
                wp_enqueue_style('ar_styles_custom', plugins_url('ar-for-woocommerce/assets/css/ar-display-custom.css'), false, '1.0.0', 'all');
            }
        
            return '';
        }
    
        /*********** Display the AR Alternate Model ***********/
    
       public function ar_alternative_model($alt_id, $suffix=''){        
            global $wp, $ar_plugin_id, $ar_whitelabel, $ar_css_names, $ar_css_styles;
        
            $output = '';
        
            $atts['id'] = $alt_id;
            $ar_model = new AR_Model($atts);
            $model_array = $ar_model->model_array;
            $model_array['ar_model_atts'] = $atts;
        
            $ar_model_id = $model_array['model_id'] ?? '';
        
            if (strpos($ar_model_id, ',') !== false) {
                $ar_model_id_array = explode(',', $ar_model_id);
                $ar_model_id = str_replace(" ","",implode("_",$ar_model_id_array));
            }
        
            $model_array['ar_environment'] = get_post_meta($atts['id'], '_ar_environment'.$suffix, true) 
                ? 'environment-image="' . get_post_meta($atts['id'], '_ar_environment'.$suffix, true) . '"'
                : '';
        
            $model_array['ar_poster'] = get_post_meta($atts['id'], '_ar_poster'.$suffix, true) 
                ? get_post_meta($atts['id'], '_ar_poster'.$suffix, true) . '"'
                : '';
        
            $model_array['skybox_file'] = !empty($model_array['skybox_file']) 
                ? ' skybox-image="' . $model_array['skybox_file'] . '"'
                : '';
        
            $model_array['ar_resizing'] = ($model_array['ar_resizing'] ?? '') == 1 
                ? ' ar-scale="fixed"' 
                : '';
        
            $viewers = ($model_array['ar_scene_viewer'] ?? '') == 1 
                ? 'scene-viewer webxr quick-look' 
                : 'webxr scene-viewer quick-look';
        
            $show_ar = ' ar ar-modes="' . $viewers . '" ';
        
            $model_array['ar_autoplay'] = !empty($model_array['ar_autoplay']) ? 'autoplay' : '';
            $model_array['ar_disable_zoom'] = !empty($model_array['ar_disable_zoom']) ? 'disable-zoom' : '';
            $model_array['ar_field_of_view'] = !empty($model_array['ar_field_of_view']) 
                ? 'field-of-view="' . $model_array['ar_field_of_view'] . 'deg"' 
                : 'field-of-view=""';
        
            $model_array['ar_qr_image'] = $model_array['ar_qr_image'] ?? '';
        
            $min_theta = 'auto';
            $min_pi = 'auto';
            $min_zoom = '20%';
            $max_theta = 'Infinity';
            $max_pi = 'auto';
            $max_zoom = '300';
        
            if (!empty($model_array['ar_zoom_in']) && $model_array['ar_zoom_in'] != 'default') {
                $model_array['ar_zoom_in'] = 100 - $model_array['ar_zoom_in'];
                $min_zoom = $model_array['ar_zoom_in'] . '%"';
            }
        
            if (!empty($model_array['ar_zoom_out']) && $model_array['ar_zoom_out'] != 'default') {
                $model_array['ar_zoom_out'] = (($model_array['ar_zoom_out'] / 100) * 400) + 100;
                $max_zoom = $model_array['ar_zoom_out'] . '%"';
            }
        
            if (!empty($model_array['ar_rotate_limit'])) {
                if (!empty($model_array['ar_compass_top_value'])) $min_pi = $model_array['ar_compass_top_value'];
                if (!empty($model_array['ar_compass_bottom_value'])) $max_pi = $model_array['ar_compass_bottom_value'];
                if (!empty($model_array['ar_compass_left_value'])) $min_theta = $model_array['ar_compass_left_value'];
                if (!empty($model_array['ar_compass_right_value'])) $max_theta = $model_array['ar_compass_right_value'];
            }
        
            $ar_zoom_out_output = 'min-camera-orbit="' . $min_theta . ' ' . $min_pi . ' ' . $min_zoom . '"';
            $ar_zoom_in_output = 'max-camera-orbit="' . $max_theta . ' ' . $max_pi . ' ' . $max_zoom . '"';
        
            $model_array['ar_exposure'] = !empty($model_array['ar_exposure']) ? 'exposure="' . $model_array['ar_exposure'] . '"' : '';
            $model_array['ar_shadow_intensity'] = !empty($model_array['ar_shadow_intensity']) ? 'shadow-intensity="' . $model_array['ar_shadow_intensity'] . '"' : '';
            $model_array['ar_shadow_softness'] = !empty($model_array['ar_shadow_softness']) ? 'shadow-softness="' . $model_array['ar_shadow_softness'] . '"' : '';
        
            $model_array['ar_camera_orbit_reset'] = $model_array['ar_camera_orbit'] ?? '';
            $model_array['ar_camera_orbit'] = !empty($model_array['ar_camera_orbit']) ? 'camera-orbit="' . $model_array['ar_camera_orbit'] . '"' : '';
        
            $model_array['ar_environment_image'] = !empty($model_array['ar_environment_image']) ? 'environment-image="legacy"' : '';
            $model_array['ar_emissive'] = !empty($model_array['ar_emissive']) ? ' emissive ' : '';
            $model_array['ar_light_color'] = !empty($model_array['ar_light_color']) ? 'light-color="' . $model_array['ar_light_color'] . '"' : '';
        
            // Handle iOS AR scaling for disable resizing
            $ios_src_url = ar_get_secure_model_url($model_array['usdz_file'] ?? '');
            $glb_src_url = ar_get_secure_model_url($model_array['glb_file'] ?? '');
            
            // Check if disable resizing is enabled (check both original value and processed string)
            $ar_resizing_enabled = false;
            if (isset($model_array['ar_resizing'])) {
                // Check if it's the processed string (contains 'ar-scale="fixed"')
                if (strpos($model_array['ar_resizing'], 'ar-scale="fixed"') !== false) {
                    $ar_resizing_enabled = true;
                }
                // Or check if it's the original numeric value
                elseif ($model_array['ar_resizing'] == 1) {
                    $ar_resizing_enabled = true;
                }
            }
            
            if ($ar_resizing_enabled) {
                if (!empty($ios_src_url)) {
                    $ios_src_url .= '#allowsContentScaling=0';
                }
                if (!empty($glb_src_url)) {
                    $glb_src_url .= '#allowsContentScaling=0';
                }
            }
            
            $output .= '<div class="ar_alternative_model_container">';
            $output .= '<model-viewer id="model_' . $ar_model_id . '" ' . $show_ar;
            $output .= '
            ios-src="' . $ios_src_url . '" 
            src="' . $glb_src_url . '" 
            ' . $model_array['skybox_file'] . '
            ' . $model_array['ar_environment'] . '
            ' . $model_array['ar_resizing'] . '
            ' . $model_array['ar_field_of_view'] . '
            ' . $ar_zoom_in_output . '
            ' . $ar_zoom_out_output . '
            ' . $model_array['ar_camera_orbit'] . '
            ' . $model_array['ar_exposure'] . '
            ' . $model_array['ar_shadow_intensity'] . '
            ' . $model_array['ar_shadow_softness'] . '
            ' . $model_array['ar_environment_image'] . ' 
            ' . $model_array['ar_emissive'] . '  
            ' . $model_array['ar_light_color'] . '  
            poster="' . esc_url($model_array['ar_poster'] ? rtrim($model_array['ar_poster'], '"') : get_the_post_thumbnail_url($ar_model_id)) . '"
            alt="AR Display 3D model" 
            class="ar-display-model-viewer" 
            quick-look-browsers="safari chrome" 
            ';
        
            $output .= $model_array['ar_disable_zoom'] . '>';
        
            $output .= '<button slot="ar-button" data-id="' . $ar_model_id . '" data-plugin="' . esc_attr( $ar_plugin_id ) . '" class="ar-button ar-button-default" id="ar-button_' . $ar_model_id . '"><img id="ar-img_' . $ar_model_id . '" src="' . esc_url(plugins_url("assets/images/ar-view-btn.png", __FILE__)) . '" class="ar-button-img"></button>';
        
            $output .= '<input type="hidden" id="src_' . $ar_model_id . '" value="' . ar_get_secure_model_url($model_array['glb_file'] ?? '') . '">';
        
            $output .= '</model-viewer></div>';
        
            if (
                is_numeric($model_array['ar_x'] ?? null) &&
                is_numeric($model_array['ar_y'] ?? null) &&
                is_numeric($model_array['ar_z'] ?? null)
            ) {
                $output .= '<script>
                const modelViewerTransform' . $ar_model_id . ' = document.querySelector("model-viewer#model_' . $ar_model_id . '");
                const updateScale' . $ar_model_id . ' = () => {
                    modelViewerTransform' . $ar_model_id . '.scale = \'' . $model_array['ar_x'] . ' ' . $model_array['ar_y'] . ' ' . $model_array['ar_z'] . '\';
                };
                updateScale' . $ar_model_id . '();
                </script>';
            }
        
            return $output;
        }
        /**
         * Load a template file.
         *
         * @param string $template_name The name of the template.
         * @param array $args Arguments to pass to the template.
         */
        private function load_template( $template_name, $args = [] ) {
            extract( $args ); // Extract the args to be used as variables in the template.
            
            //$model_array = $args;
            $template_file = plugin_dir_path( dirname(__FILE__) ) . 'templates/' . $template_name . '.php';
    
            if ( file_exists( $template_file ) ) {
                include $template_file;
            }
        }
    
        public function sanitize_atts($atts){
            $temp = array();
                    
            foreach($atts as $index => $value){
                if($index == 'id'){
                    $temp[$index] = preg_replace('/[^0-9,]/', '', $value);
                } else {
                    $temp[$index] = esc_attr(strip_tags(esc_html($value)));
                }
            }
    
            return $temp;
        }
    }   
}