<?php
defined( 'ABSPATH' ) || exit;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 DEFINES

 plugin_dir_path( __FILE__ ) );	// plugin_dir_url( __FILE__ )
 version is in genolve-toolkit.php
 
 GENOLVE_JS_URL  -  where genolve js files are loaded from
 GENOLVE_ACTION_URL  - genolve ajax submit url
*/
define( 'GENOLVE_MANAGE_GROUP', 'genolve-manage-group');
define( 'GENOLVE_DASHBOARD_GROUP', 'genolve-dashboard-group');
/* TEST 
define( 'GENOLVE_ACTION_URL',  'http://localhost/widget/');
define( 'GENOLVE_JS_URL',      'http://localhost/widget/js/' );
define( 'GENOLVE_VER',      '' );
  */
/* PRODUCTION  also change version in genolve-toolkit.php, eloop and readme.txt */
define( 'GENOLVE_ACTION_URL',  'https://www.genolve.com/');		
define( 'GENOLVE_JS_URL',      'https://www.genolve.com/js/' );
define( 'GENOLVE_VER',         '-6.0.0' ); 

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_addHeaderCode -admin init functions; register options, Load css sheet for the main WordPress pages
*/
function genolve_addHeaderCode() {
	// REGISTER
	genolve_register_options();

	$user = wp_get_current_user();
	/* for more than one role
	$allowed_roles = array('editor', 'administrator', 'author');
	if( array_intersect($allowed_roles, $user->roles ) )
	*/
	wp_enqueue_script('jquery');
	$genolveO=array();
	// icons enabled in admin area
	if( get_option('genolve_enabled')=="TRUE" ){	
		//jquery-ui-core
		wp_enqueue_script('jquery-ui-core'); 
		wp_enqueue_script('jquery-ui-draggable');
   	wp_enqueue_script('jquery-ui-droppable');
		wp_enqueue_script('jquery-ui-resizable');
		// need offsite styles
		// LOCAL to plugin
		wp_enqueue_style('genolve-style', GENOLVE_PLUGIN_DIR.'css/genolve-style.css');		
		if(is_admin() ){ //  run on admin pages
			// old args, __FILE__, '' , 'all'
			wp_enqueue_script('genolve_scripts', GENOLVE_PLUGIN_DIR.'js/genolve-scripts.js',10);
			//wp_localize_script('genolve_scripts',    'genolve_enabled', array(get_option("genolve_enabled"))  );	
			}
		else { // dont run on admin pages
			//                       TAG              PATH                                            dependency   VER   PUTinFOOTER
			wp_register_script('genolve_getsvg', GENOLVE_PLUGIN_DIR.'js/genolve-getsvg.js' );
			//                       TAG              PATH                                            dependency   VER  
			//wp_enqueue_script('genolve_getsvg', plugins_url('js/genolve-getsvg.js', __FILE__), __FILE__, '' , 'all'); 
			wp_enqueue_script('genolve_getsvg');
			wp_register_script('genolve_scroll', GENOLVE_PLUGIN_DIR.'js/genolve-scroll.js' );
			wp_enqueue_script('genolve_scroll');
			wp_register_script('genolve_sound', GENOLVE_PLUGIN_DIR.'js/genolve-sound.js' );
			wp_enqueue_script('genolve_sound');
			wp_register_script('genolve_3rdparty', GENOLVE_PLUGIN_DIR.'js/genolve-3rdparty.js' );
			wp_enqueue_script('genolve_3rdparty');
			wp_register_script('genolve_howler', GENOLVE_PLUGIN_DIR.'js/howler.min.js' );
			wp_enqueue_script('genolve_howler');
			wp_register_script('genolve_snap', GENOLVE_PLUGIN_DIR.'js/snap-0.5.1.js' );
			wp_enqueue_script('genolve_snap');
			wp_register_script('genolve_d3', GENOLVE_PLUGIN_DIR.'js/d3.min.js' );
			wp_enqueue_script('genolve_d3');
			}
		// load up genolve editor files for any valid wp user
		//if(  current_user_can('edit_posts')  ){
		if(  is_user_logged_in()  ){
			// COLOR SELECTOR for dashboard
			/*
				//add_action( 'admin_enqueue_scripts', 'mw_enqueue_color_picker' );
				//function mw_enqueue_color_picker( $hook_suffix ) {
    		// first check that $hook_suffix is appropriate for your admin page
    		wp_enqueue_style( 'wp-color-picker' );
				
    		//wp_enqueue_script( 'genolve-color-picker', plugins_url('my-script.js', __FILE__ ), array( 'wp-color-picker' ), '1.0', true );
				//wp_enqueue_script('wp-color-picker');
				
				//wp_register_script('genolve_meta', GENOLVE_PLUGIN_DIR.'js/genolve-meta.js', array( 'wp-color-picker' ) );
				//wp_register_script('genolve_meta', GENOLVE_PLUGIN_DIR.'js/genolve-meta.js' );
				 wp_enqueue_script(
						'genolve_meta',
						GENOLVE_PLUGIN_DIR.'js/genolve-meta.js',
						array( 'jquery', 'wp-color-picker' ), // Dependencies array: jQuery is often required for the color picker
						'1.0.0',
						true // Load script in the footer
						);
				//wp_enqueue_script('genolve_meta');
				*/
				function my_custom_color_picker_scripts() {
					// Enqueue the wp-color-picker stylesheet
					wp_enqueue_style( 'wp-color-picker' );
			
					// Enqueue your custom script, declaring 'wp-color-picker' as a dependency
					wp_enqueue_script(
							'genolve_meta',
							GENOLVE_PLUGIN_DIR.'js/genolve-meta.js',
							array( 'wp-color-picker', 'jquery' ), // Add 'jquery' as a dependency as well, as wp-color-picker relies on it
							'1.0',
							true // Load in the footer
							);
					}
				add_action( 'admin_enqueue_scripts', 'my_custom_color_picker_scripts' );

				wp_register_script('genolve_customize', GENOLVE_PLUGIN_DIR.'js/genolve-customize.js' );
				wp_enqueue_script('genolve_customize');
				
				//BOOTSTRAP
				wp_enqueue_script('genolve_popper', GENOLVE_PLUGIN_DIR.'js/bootstrap-4-0-ns/js/popper.min.js');
				wp_enqueue_script('genolve_bootstrap', GENOLVE_PLUGIN_DIR.'js/bootstrap-4-0-ns/js/bootstrap.min.js');
				wp_enqueue_style('genolve-style-bootstrap', GENOLVE_PLUGIN_DIR.'js/bootstrap-4-0-ns/css/bootstrap-ns.css');
				wp_enqueue_style('genolve-style-openiconic', GENOLVE_PLUGIN_DIR.'js/open-iconic/font/css/open-iconic-bootstrap.css');

				}
		//localize IMG
		$genolve_img_sel_hash=array();
		$genolve_img_sel=get_option("genolve_img_sel");
		$genolve_img_val=get_option("genolve_img_val");
		$genolve_img_par=get_option("genolve_img_par");
		$looper =(gettype($genolve_img_sel)=='string')?0:count($genolve_img_sel);
		for($ii=0;$ii<$looper;$ii++){
			// remove extension .jpg .ogv .mp4
			//$genolve_img_sel_hash[ preg_replace("/(.jpg|.ogv|.mp4)$/","",$genolve_img_sel[$ii]) ]=$genolve_img_val[$ii];
			$theval = (gettype($genolve_img_val)=='array'&&count($genolve_img_val)>$ii)?$genolve_img_val[$ii]:'badtype:'.gettype($genolve_img_val).' or size:'.count($genolve_img_val);
			$thepar = (gettype($genolve_img_par)=='array'&&count($genolve_img_par)>$ii)?$genolve_img_par[$ii]:'badtype:'.gettype($genolve_img_par).' or size:'.count($genolve_img_par);
			$genolve_img_sel_hash[ preg_replace("/(.jpg|.ogv|.mp4)$/","",$genolve_img_sel[$ii]) ]=array('val'=>$theval,'par'=>$thepar);
			}
		//echo "genolve_img_sel_hash:type:".gettype($genolve_img_sel_hash)." size:".count($genolve_img_sel_hash);
		wp_localize_script('genolve_getsvg', 'genolve_img_sel_hash', count($genolve_img_sel_hash)>0?$genolve_img_sel_hash:array("{}") );		// LOCALIZE IMG JS VARS
		
		//localize GENERAL
		$genolve_gen_sel_hash=array();
		$genolve_gen_sel=get_option("genolve_gen_sel");
		$genolve_gen_val=get_option("genolve_gen_val");
		$genolve_gen_par=get_option("genolve_gen_par");
		// found case where deleting from manage leaves genolve_gen_val genolve_gen_sel in DB but empty strings
		//echo "looping genolve_gen_sel type:". gettype($genolve_gen_sel)."count:".count($genolve_gen_sel)." dump:".$genolve_gen_sel." genolve_gen_val:".count($genolve_gen_val)." genolve_gen_par:".count($genolve_gen_par);
		$looper =(gettype($genolve_gen_sel)=='string')?0:count($genolve_gen_sel);
		for($ii=0;$ii<$looper;$ii++){
			//$genolve_gen_sel_hash[ $genolve_gen_sel[$ii] ]=$genolve_gen_val[$ii];
			$genolve_gen_sel_hash[ $genolve_gen_sel[$ii] ]=array('val'=>$genolve_gen_val[$ii],'par'=>$genolve_gen_par[$ii]);;
			}
		wp_localize_script('genolve_getsvg', 'genolve_gen_sel_hash', count($genolve_gen_sel_hash)>0?$genolve_gen_sel_hash:array("{}") );		// LOCALIZE TAG JS VARS
		
		/* JS vars getsvg customize*/
		//echo "DATA DATA DATA data:".get_option("genolve_enabled").",". get_option("genolve_membership").",". wp_get_theme()->get('Name') ;
		$genolve_ver = GENOLVE_VER;
		if($genolve_ver =='')$genolve_ver="notset";
		$genolveO=array();
		$genolveO['genolve_enabled']= get_option("genolve_enabled");	
		$genolveO['genolve_membership']= get_option("genolve_membership");
		$genolveO['wpajaxurl']= admin_url( 'admin-ajax.php' );	
		$genolveO['wptheme']= wp_get_theme()->get('Name') ;
		$genolveO['wpuser']= $user->user_login;//get_current_user_id();
		$curlimit =  get_the_author_meta( 'genolve_credlimit', $user->ID ) ;
		$genolveO['credlimit']= $curlimit==""?"":floatval($curlimit)/100; // convert to $ to match others
		$genolveO['GENOLVE_VER']= $genolve_ver ;	
		$genolveO['jsbasedir']= GENOLVE_JS_URL;
		$genolveO['vv']= 'true';	
		$genolveO['genolve_use_mode']= get_option("genolve_use_mode") ?get_option("genolve_use_mode"):'none' ;
		$genolveO['genolve_save_ai']= get_option("genolve_save_ai") ?get_option("genolve_save_ai"):'none' ;
		$genolveO['genolve_color_bg']= get_option("genolve_color_bg") ?get_option("genolve_color_bg"):'none' ;
		$genolveO['genolve_color_txt']= get_option("genolve_color_txt")?get_option("genolve_color_txt"):'none' ;
		$genolveO['genolve_color_brdr']= get_option("genolve_color_brdr")?get_option("genolve_color_brdr"):'none' ;
		//genolve_start_credits,genolve_credits_mode,genolve_markup
		// not needed in js $genolveO['genolve_start_credits']= get_option("genolve_start_credits");
		$genolveO['genolve_credits_mode']= get_option("genolve_credits_mode");
		$genolveO['gmarkup']= get_option("genolve_markup");
		$genolveO['genolve_buy_link']= get_option("genolve_buy_link");
		$genolveO['beyonce_getsvg']= wp_create_nonce( 'beyonce_getsvg' );	
		$genolveO['beyonce_customize']= wp_create_nonce( 'beyonce_customize' );	
		
		
		wp_localize_script('genolve_customize', 'genolveO', $genolveO);	
		wp_localize_script('genolve_getsvg', 'genolveO', $genolveO);

		} // end genolve enabled
	}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
201904 shortcodes not used
 genolve_shortcodeHandler - Function to do the work of the plugin and return shortcode text

function genolve_shortcodeHandler() {
	$genolve_output = genolve_outputFunction(); //inc/output.php
	return $genolve_output;
}
*/
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_install- Runs on plugin install, adds all DB option keys, displays activation message
*/
function genolve_install() {
	//Populate new option fields with default values
	global $wpdb;
	$genolve_apikey = '';
	$genolve_enabled= 'TRUE';
	$genolve_version= GENOLVE_VER;
	// new  expandable tag OBJ
	$genolve_tag_options=array(
						 'tagsel1'=>'.wp-post-image',
						 'tagval1'=>'http://localhost/widget/athena/en/ZlistControl.php?CMD=GETSVG&displayformat=562_196&viewBox=0_0_573_200&projID=111&DEX=0x201804020010127638795803F6AD003E',
						 'tagsel2'=>'.footer',
						 'tagval2'=>''
				 );
	
	// Creates new database fields
	// in WP options table: option_name,option_value,autoload

	if(!get_option('genolve_apikey'))
		add_option("genolve_apikey", $genolve_apikey, '', 'yes');
	if(!get_option('genolve_version'))
		add_option("genolve_version", $genolve_version, '', 'yes');
	if(!get_option('genolve_use_mode'))
		add_option("genolve_use_mode", $genolve_use_mode="notset", '', 'yes');
	if(!get_option('genolve_save_ai'))
		add_option("genolve_save_ai", $genolve_save_ai="notset", '', 'yes');
	//genolve_reseller,genolve_start_credits,genolve_credits_mode,genolve_markup
	//if(!get_option('genolve_reseller'))		add_option("genolve_reseller", $genolve_reseller=FALSE, '', 'yes');
	if(!get_option('genolve_start_credits'))
		add_option("genolve_start_credits", $genolve_start_credits=0, '', 'yes');
	if(!get_option('genolve_credits_mode'))
		add_option("genolve_credits_mode", $genolve_credits_mode='credoff', '', 'yes');
	if(!get_option('genolve_markup'))
		add_option("genolve_markup", $genolve_markup=0, '', 'yes');
	if(!get_option('genolve_buy_link'))
		add_option("genolve_buy_link", $genolve_buy_link='', '', 'yes');
	// color
	if(!get_option('genolve_color_bg'))
		add_option("genolve_color_bg", $genolve_color_bg="#880000", '', 'yes');
	if(!get_option('genolve_color_txt'))
		add_option("genolve_color_txt", $genolve_color_txt="#000000", '', 'yes');
	if(!get_option('genolve_color_brdr'))
		add_option("genolve_color_brdr", $genolve_color_brdr="#666666", '', 'yes');
	if(!get_option('genolve_tag_options'))
		add_option("genolve_tag_options", $genolve_tag_options, '', 'yes');// notused genolve_gen_tag
	if(!get_option('genolve_gen_sel')){
		$genolve_gen_sel=array();
		add_option("genolve_gen_sel", $genolve_gen_sel, '', 'yes');
		}
	if(!get_option('genolve_gen_val')){
		$genolve_gen_val=array();
		add_option("genolve_gen_val", $genolve_gen_val, '', 'yes');
		}
	if(!get_option('genolve_gen_par')){
		$genolve_gen_par=array();
		add_option("genolve_gen_par", $genolve_gen_par, '', 'yes');
		}
	if(!get_option('genolve_img_sel')){
		$genolve_img_sel=array();
		add_option("genolve_img_sel", $genolve_img_sel, '', 'yes');
		}
	if(!get_option('genolve_img_val')){
		$genolve_img_val=array();
		add_option("genolve_img_val", $genolve_img_val, '', 'yes');
		}
	if(!get_option('genolve_img_par')){
		$genolve_img_par=array();
		add_option("genolve_img_par", $genolve_img_par, '', 'yes');
		}
		//
	if(!get_option('genolve_enabled'))
		add_option("genolve_enabled", $genolve_enabled, '', 'yes');	
	if(!get_option('genolve_membership')){
		$genolve_membership="Basic";
		add_option("genolve_membership", $genolve_membership, '', 'yes');
		}
	if(!get_option('genolve_block_separator'))
		add_option("genolve_block_separator", 'nothing set', '', 'yes');
	// install message:
	// https://stackoverflow.com/questions/38233751/show-message-after-activating-wordpress-plugin?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
	set_transient( 'genolve-transient-notice', true, 5 );
	$mydata =  genolve_proxy(
										array('faction' => "control",
										'keylist' => 'CMD,redir,param1,param2',
										'CMD' => 'STATUSUPDATE',
										'param1' => 'active',
										'param2' => wp_get_theme()->get('Name'),
										'beyonce_skip' => true,
										'redir' => 'JSON') 
										);
	} // end install
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_register_options - register custom options
 https://codex.wordpress.org/Creating_Options_Pages
*/
function genolve_register_options() { // whitelist options
	//MANAGE
	$mygroup = GENOLVE_MANAGE_GROUP;
	register_setting( $mygroup, 'genolve_gen_sel' );
	register_setting( $mygroup, 'genolve_gen_val' );
	register_setting( $mygroup, 'genolve_gen_par' );
	register_setting( $mygroup, 'genolve_img_sel' );
	register_setting( $mygroup, 'genolve_img_val' );
	register_setting( $mygroup, 'genolve_img_par' );
	
	//DASHBOARD
	$mygroup = GENOLVE_DASHBOARD_GROUP;
	register_setting( $mygroup, 'genolve_apikey' );
	register_setting( $mygroup, 'genolve_use_mode' );
	register_setting( $mygroup, 'genolve_save_ai' );
	//genolve_reseller,genolve_start_credits,genolve_credits_mode,genolve_markup
	//register_setting( $mygroup, 'genolve_reseller' );
	register_setting( $mygroup, 'genolve_start_credits' );
	register_setting( $mygroup, 'genolve_credits_mode' );
	register_setting( $mygroup, 'genolve_markup' );
	register_setting( $mygroup, 'genolve_buy_link' );
	
	//color
	register_setting( $mygroup, 'genolve_color_bg' );
	register_setting( $mygroup, 'genolve_color_txt' );
	register_setting( $mygroup, 'genolve_color_brdr' );
	register_setting( $mygroup, 'genolve_enabled' );
	
	//RESERVED or code-only options
	//register_setting( $mygroup, 'genolve_version' );
	//register_setting( $mygroup, 'genolve_params' );
	//register_setting( $mygroup, 'genolve_tag_options' );
	//register_setting( $mygroup, 'genolve_membership' );
	//register_setting( $mygroup, 'genolve_block_separator' );

}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_deactivate -Runs on deactivation stops all updates
*/
function genolve_deactivate() {
	$mydata =  genolve_proxy(
										array('faction' => "control",
										'keylist' => 'CMD,redir,param1,param2',
										'CMD' => 'STATUSUPDATE',
										'param1' => 'inactive',
										'param2' => wp_get_theme()->get('Name'),
										'beyonce_skip' => true,
										'redir' => 'JSON') 
										);
	// stop any email messages
	} // end deactivate
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_remove -Runs on uninstall and deletes the database fields
*/
function genolve_remove() {
	$mydata =  genolve_proxy(
										array('faction' => "control",
										'keylist' => 'CMD,redir,param1,param2',
										'CMD' => 'STATUSUPDATE',
										'param1' => 'deleted',
										'param2' => wp_get_theme()->get('Name'),
										'beyonce_skip' => true,
										'redir' => 'JSON') 
										);
	delete_option('genolve_apikey');
	delete_option('genolve_version');
	delete_option('genolve_use_mode');
	delete_option('genolve_save_ai');
	//genolve_reseller,genolve_start_credits,genolve_credits_mode,genolve_markup
	//delete_option('genolve_reseller');
	delete_option('genolve_start_credits');
	delete_option('genolve_credits_mode');
	delete_option('genolve_markup');
	delete_option('genolve_buy_link');
	//color
	delete_option('genolve_color_bg');
	delete_option('genolve_color_txt');
	delete_option('genolve_color_brdr');
	delete_option('genolve_tag_options');
	delete_option('genolve_gen_sel');
	delete_option('genolve_gen_val');
	delete_option('genolve_gen_par');
	delete_option('genolve_img_sel');
	delete_option('genolve_img_val');
	delete_option('genolve_img_par');
	delete_option('genolve_enabled');
	delete_option('genolve_membership');
	delete_option('genolve_block_separator');
	} // end remove
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  genolve_registerWidget - Register the widget
*/
function genolve_registerWidget() {
	register_widget('genolve_widget');
	}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	genolve_userbasic - user agreed to show genolve link 
*/
function genolve_userbasic(){
	if(get_option("genolve_membership")=="BasicPlus" &&  ! is_admin())//get_option("genolve_membership")
		echo '<a class="gnlv-logo-lr" id="genolve-powered-by" href="https://www.genolve.com" target="_blank">animations by genolve</a>';
	}
//  AJAX                  AJAX               AJAX                HANDLERS BELOW
//  AJAX                  AJAX               AJAX                HANDLERS BELOW
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	genolve_send_json - send ajax response
*/
function genolve_send_json( $response ) {
		//@header( 'Content-Type: application/json; charset=utf-8'  );
		//20180524 the BADREQUSTBUG  remove: charset=utf-8   > chrome still bad
    //@header( 'Content-Type: application/json; charset=utf-8'  );
    echo wp_json_encode( $response );
    wp_die();
		}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
	genolve_send_json_error - send ajax error message
*/
function genolve_send_json_error( $msg ) {
		$jsonRespA=array('result' => 'error', 
            'message' => $msg, 
            'success' => false );
		genolve_send_json( $jsonRespA );
		}

// adding a new one? dont forget the add_action( 'wp_ajax_
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_proxy - wp_ajax post : curl forward _POST to genolve and echo response (most all calls from javascript are in echo mode)
                         OR direct call by setting arg postO
  expecting POSTvars faction - the forward action
                     keylist - the list of vars to forward
*/
function genolve_proxy( $postO=null ){
	/*
   if( !class_exists( 'WP_Http' ) )
        include_once( ABSPATH . WPINC. '/class-http.php' );
  $request = new WP_Http;
  $result = $request->request( $faction, array( 'method' => 'POST', 'body' => $jsonRespA) );
	*/
	$mode  = (($postO==null)?"echo":"return");
	if($mode=="echo")
		$postO = $_POST;
		
	$faction = sanitize_text_field($postO['faction']);
	if($faction=="track")
		$faction=GENOLVE_ACTION_URL.'athena/en/track.php'; 
	else if($faction=="evolve")
		$faction=GENOLVE_ACTION_URL.'svg/en/evolve.php';
	else if($faction=="control")
		$faction=GENOLVE_ACTION_URL.'athena/en/ZlistControl.php'; 
	else
		genolve_send_json_error("Error: genolve_proxy called with no faction or invalid:"+$faction);
	$keylist = sanitize_text_field($postO['keylist']);
	$keyA = preg_split("/,/",$keylist);
	$apikey = get_option('genolve_apikey');
	$jsonRespA=array('apikey' => $apikey); 
	for($ii=0;$ii<count($keyA);$ii++){
		if(preg_match("/^beyonce/",$keyA[$ii]) )
			$mybeyonce=$keyA[$ii];
		if(array_key_exists($keyA[$ii],$postO))
			$jsonRespA[ $keyA[$ii] ]=$postO[ $keyA[$ii] ];
		}
	//$retval=check_ajax_referer('beyonce','security',true);
	if(array_key_exists('beyonce_skip',$postO) && $postO['beyonce_skip']==true)
		$mybeyonce="skip";//skip for PHP initiated calls
	else{
		$retval=check_ajax_referer($mybeyonce,$mybeyonce,false);
		////if(  ($mybeyonce=="beyonce_customize" && !current_user_can('edit_posts')) || !$retval )
		if(  ($mybeyonce=="beyonce_customize" && !is_user_logged_in()) || !$retval )
			genolve_send_json_error("Error: user not logged in:". is_user_logged_in() ." or nonce fail:".$retval);
		}
	$jsonRespA = wp_unslash($jsonRespA); // 20260323 remove any autoadded slash  cat's -> cat\'s
	$result = wp_remote_post( $faction, array(
																			'method' => 'POST',
																			'timeout' => 170,  //20250116 120 -> 170  do not want to trigger before cloudflare timeout
																			'redirection' => 5,
																			//'httpversion' => '1.0',
																			'blocking' => true,
																			'headers' => array( //20230523 add empty expect as hack for larger files
																					//'Content-Type' => 'application/json',
        																	'Expect' => '',),
																			'cookies' => array(),
																			'body' => $jsonRespA //dont work wp_json_encode($jsonRespA,JSON_HEX_QUOT ) 
																				) );
// result.headers 
// result.body
// result.response.[code,message]
// result.cookies
// debug:
///echo "body:".$result['body']." <br>===================response:".$result['response'];
	if ( is_wp_error( $result ) ) {// errors
			$stuff = $result->get_error_message();
			if( array_key_exists('body',$result))
				$stuff .= "<br>RESULT.BODY first 3000 chars:".substr($result['body'],0,3000);
			genolve_send_json_error( $stuff );
		}
	else { //good2go
		//$thebody = $result['body'];
		$thebody = wp_remote_retrieve_body( $result );
		/* debug yes, always expect type string		genolve_send_json_error("genolve_proxy: mode:".$mode." got body type:".gettype($thebody) ." body dump:".$thebody);		
		genolve_send_json_error("genolve_proxy: got type:".gettype($thebody) ." this proves the bad request NOT CAUSED by svg because there is no svg");
		*/

		
		if(gettype($thebody)=="string" && preg_match("/^{/",$thebody) ){ // should be already encoded JSON!!!!
			if($mybeyonce!="skip")
				$thebody = preg_replace("/^{/",'{"'.$mybeyonce.'":"'.wp_create_nonce($mybeyonce).'",',$thebody);
			// special processing
			$thebodyJ=json_decode($thebody,true); // remove true for property_exists($thebodyJ,'newapikey') 
			// dont show apikey in JS, this transition hack can be deleted after all users upgrade to 4.0.7
			if(!empty($thebodyJ) && array_key_exists('apikey',$thebodyJ) && !array_key_exists('newapikey',$thebodyJ) )
			  //"apikey":"8stuff",
				$thebody = preg_replace("/.apikey.:.*?,/",'',$thebody);//unset($thebodyJ['apikey']);
			if(!empty($thebodyJ) && array_key_exists('newapikey',$thebodyJ) && $thebodyJ['newapikey'] !=null )// set it
				if( get_option("genolve_apikey")==null )// set it
					update_option("genolve_apikey", sanitize_text_field($thebodyJ['newapikey'] ) );
			if(!empty($thebodyJ) && array_key_exists('errorcode',$thebodyJ) && $thebodyJ['errorcode']=='ER_APIKEY')
				if($mode=="echo")
					$thebody = preg_replace("/^{/",'{"admin_email":"'.get_bloginfo('admin_email').'","wptheme":"'.wp_get_theme()->get('Name').'",',$thebody);
				else {//add option for autoregister
					$thebodyJ['admin_email']=get_bloginfo('admin_email');
					$thebodyJ['wptheme']=wp_get_theme()->get('Name');
				}
				
		 	if($mode=="echo") // _POST mode
				echo  $thebody ; 
			else 
				return $thebodyJ;
    	wp_die();
			}
		// show an error
		$numchars = gettype($thebody)=="array"?count($thebody):    (gettype($thebody)=="string"?strlen($thebody):0);
		genolve_send_json_error("genolve_proxy: The server did not return expected type, got type:".gettype($thebody)." num chars:".$numchars." first 3000 chars:".substr($thebody,0,3000));
		}// end good2go
	// 
	// seeing BAD REQUEST bug ?
	// 
	// https://stackoverflow.com/questions/20664341/bad-request-error-when-posting-data-using-jquery-in-ie-only?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
	//causes error header('Content-Type: application/json'); // for jsonp application/javascript
	//
	//echo json_encode( $jsonRespA );	
	//wp_die();
	} // end proxy
	
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_setOpt - wp_ajax post : Set genolve block options like genolve_block_separator
 called by: eloop
*/
function genolve_setOpt(){
	$retval=check_ajax_referer('beyonce_customize','beyonce_customize',false);
	if(  !current_user_can('edit_posts') || !$retval )
		genolve_send_json_error("Error: user lacks permissions:".current_user_can('edit_posts')." or nonce fail:".$retval);

	// Whitelist of allowed options to prevent arbitrary options update vulnerability
	$allowed_options = array(
		'genolve_enabled',
		'genolve_membership',
		'genolve_use_mode',
		'genolve_save_ai',
		'genolve_color_bg',
		'genolve_color_txt',
		'genolve_color_brdr',
		'genolve_start_credits',
		'genolve_credits_mode',
		'genolve_markup',
		'genolve_buy_link',
		'genolve_tag_options',
		'genolve_gen_sel',
		'genolve_gen_val',
		'genolve_gen_par',
		'genolve_img_sel',
		'genolve_img_val',
		'genolve_img_par',
		'genolve_block_separator',
	);

	$thesvg = sanitize_text_field($_POST['thesvg']);
	$theopt = sanitize_key($_POST['theopt']);
	$themem = sanitize_text_field($_POST['themem']);

	// Validate option is in whitelist before updating
	if ( !in_array( $theopt, $allowed_options, true ) ) {
		genolve_send_json_error("Error: option not allowed:".$theopt);
	}

	update_option($theopt,$thesvg);
	$jsonRespA=array('result' => 'success',
								'message' => 'Selections saved!',
								'success' => true,
								'beyonce_customize' => wp_create_nonce( 'beyonce_customize' )  );
	genolve_send_json( $jsonRespA );
	}// end genolve_setOpt

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_setMet - wp_ajax post : Set genolve user metadata 
 expects: wpuser,metaname,theval
 called by: eloop
*/
function genolve_setMet(){
	$retval = check_ajax_referer('beyonce_customize','beyonce_customize',false);
	$wpuser = sanitize_text_field($_POST['wpuser']);
	$user   = wp_get_current_user();
	if(  $wpuser != $user->user_login || !$retval || !current_user_can( 'edit_user', $user->ID ))
		genolve_send_json_error("Error: user missmatch:".$wpuser."!=".$user->user_login." or nonce fail:".$retval);
	
	$theval = intval(sanitize_key($_POST['theval']));// will be creditsUsed converted to CREDITS
	// no conversion $theval = round(floatval($theval)*100);
	$themet = 'genolve_credlimit'; // could be $_POST['metaname']
	if($themet == "genolve_credlimit"){// do decrement, only called for credbalance mode
		$curlimit  = intval(get_the_author_meta( 'genolve_credlimit', $user->ID )) ; // CREDITS BALANCE
		$theval = ($theval < $curlimit) ? ($curlimit - $theval): 0;
		}
  update_user_meta( $user->ID, $themet, $theval );
	$jsonRespA=array('result' => 'success', 
								'message' => 'Meta saved!', 
								'success' => true,
								'beyonce_customize' => wp_create_nonce( 'beyonce_customize' )  );
	genolve_send_json( $jsonRespA );	
	}// end genolve_setOpt
	
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_add2list - wp_ajax post : add on to genolve_gen_sel
  expecting POSTvars: thesel,thesvg,thepar,themem
*/
function genolve_add2list(){
	$retval=check_ajax_referer('beyonce_customize','beyonce_customize',false);
	if(  !current_user_can('edit_posts') || !$retval )
		genolve_send_json_error("Error: user lacks permissions:".current_user_can('edit_posts')." or nonce fail:".$retval);
	$thesel = sanitize_text_field($_POST['thesel']);
	$thesvg = sanitize_text_field($_POST['thesvg']);  // base64 looks like text: data:image/svg+xml;base64,PHN2Z
	$thepar = sanitize_text_field($_POST['thepar']);
	$themem = sanitize_text_field($_POST['themem']);
	// get current list
	$genolve_gen_sel=get_option("genolve_gen_sel");
	$genolve_gen_val=get_option("genolve_gen_val");
	$genolve_gen_par=get_option("genolve_gen_par");
	if (gettype($genolve_gen_sel) != "array") {
		$genolve_gen_sel=array();
		$genolve_gen_val=array();
		$genolve_gen_par=array();
		}
	// UPDATE
	$isnew=true;
	for($ii=0;$ii<count($genolve_gen_sel);$ii++){
		if($thesel == $genolve_gen_sel[$ii]){
			$isnew=false;
			$genolve_gen_val[$ii]=$thesvg;
			$genolve_gen_par[$ii]=$thepar;
			continue;
			}
		}
	// NEW
	if($isnew){
		array_push($genolve_gen_sel,$thesel);
		array_push($genolve_gen_val,$thesvg);
		array_push($genolve_gen_par,$thepar);
		}
	update_option("genolve_gen_sel",$genolve_gen_sel);
	update_option("genolve_gen_val",$genolve_gen_val);
	update_option("genolve_gen_par",$genolve_gen_par);
	update_option("genolve_membership",$themem);
	$jsonRespA=array('result' => 'success', 
								'message' => 'Selections saved!', 
								'success' => true,
								'beyonce_customize' => wp_create_nonce( 'beyonce_customize' )  );
	genolve_send_json( $jsonRespA );	
	} // end add2list
	
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_delit - wp_ajax post : delete from genolve_img_sel
  expecting: DEX to delete
*/
function genolve_delit($postO=null){
	$message = "notset";
	if($postO==null)
			$postO = $_POST;
	$retval=check_ajax_referer('beyonce_customize','beyonce_customize',false);
	if(  !current_user_can('edit_posts') || !$retval || $postO==null )
		genolve_send_json_error("Error:delit: user lacks permissions:".current_user_can('edit_posts')." or nonce fail:".$retval." or no arg:".$postO);
	$code = sanitize_text_field($postO['code']);
	// get current lists
	$genolve_img_sel=get_option("genolve_img_sel");
	$genolve_img_val=get_option("genolve_img_val");
	$genolve_img_par=get_option("genolve_img_par");
	if (gettype($genolve_img_sel) != "array" || count($genolve_img_sel)<1) 
		genolve_send_json_error("Error:delit: nothing in genolve_img_sel:".gettype($genolve_img_sel) );
	$index = array_search($code, $genolve_img_val);
	if($index===false)
		$message = "Notice:delit: did not find:".$code;
	else{
		array_splice($genolve_img_sel, $index, 1);
		array_splice($genolve_img_val, $index, 1);
		array_splice($genolve_img_par, $index, 1);
		update_option("genolve_img_sel",$genolve_img_sel);
		update_option("genolve_img_val",$genolve_img_val);
		update_option("genolve_img_par",$genolve_img_par);
		$message = "Notice:delit found and removed:".$code;
		}
	$jsonRespA=array('result' => 'success', 
								'message' => $message, 
								'success' => true,
								'beyonce_customize' => wp_create_nonce( 'beyonce_customize' )  );
	genolve_send_json( $jsonRespA );
	}// end delit
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_savefile - wp_ajax post : save remote genolve image/video and store in Media
 javascript side:jqsubmit2.sharetwitter
 example input:
action: genolve_savefile
thelink: https://genolve-video.s3.us-east-2.amazonaws.com/2020/08/summer-breeze.mp4
thepost: 
thedesc: summer breeze
beyonce_customize: e1b0d266e6
*/
function genolve_savefile($postO=null) {
		 if($postO==null)
				$postO = $_POST;
		 if ( !function_exists('media_handle_upload') ) {
			require_once(ABSPATH . "wp-admin" . '/includes/image.php');
			require_once(ABSPATH . "wp-admin" . '/includes/file.php');
			require_once(ABSPATH . "wp-admin" . '/includes/media.php');
    		}
		$retval  = check_ajax_referer('beyonce_customize','beyonce_customize',false);
		if(  !current_user_can('edit_posts') || !$retval )
			genolve_send_json_error("Error: user lacks permissions:".current_user_can('edit_posts')." or nonce fail:".$retval);
		$url     = esc_url_raw($postO['thelink']);	
		$pid     = intval($postO['thepost']);	
		$desc    = sanitize_text_field($postO['thedesc']);
		$themode = "";
		if(array_key_exists('themode',$postO))
			$themode = sanitize_key($postO['themode']);
		$theslot = "";
		if(array_key_exists('theslot',$postO))
			$theslot = sanitize_text_field($postO['theslot']);
		$thekey  = "";
		if(array_key_exists('thekey',$postO))
			$thekey  = sanitize_key($postO['thekey']);
		$dmsg    = "";
		if($desc==null)$desc="";	
		$origurl = $url;
		//20200913 if called 'justimg' respect extension
		if($themode != "justimg")
			$url = preg_replace("/(mp4|ogv)$/",'jpg',$url);

		//$url = preg_replace("/jpg$/",'svg',$url);
		// this was to test direct save of svg (not allowed)
		////$url = "https://www.genolve.com/svg/imgu/2017/06/quotes-ce8964b2-966b-448e-b09e-dc9eb7f45163.svg";
		// is this not working??    
		//                               there can be no dash in the base name
		$ext = preg_replace("/.*\./","",$url);
		$nam = preg_replace("/.*\//","",$url);//strip all path info
		$reg = '/\.'. $ext .'$/';
		
		$cod = preg_replace($reg,"",$nam); // strip the extension
		if(!preg_match("/^https:\/\/genolve-video/",$origurl) && false){//20210524 disable old mode, no more categories
			$codA = explode('-', $cod,2); //cut off category tag
			$cod = $codA[count($codA)-1];
			}
		if($themode == "justimg")
			$randname = $nam;
		else
			//$randname = "genolve". date("YmdHis").".".$ext;
			$randname = "genolve-". $nam;
		
		//$validLink = $this->checkValidLink( $url );
		//check_ajax_referer()
		$validLink = false;
		if($themode == "justimg" && (preg_match("/.*(pixabay|wikimedia).*/",$url)>0)){
			$validLink = true;
			}
		else if(preg_match("/^http:\/\/localhost/",$url)>0 || preg_match("/^https:\/\/www\.genolve\.com/",$url)>0 || preg_match("/static\.genolve\.com/",$url)>0 ||
			preg_match("/^https:\/\/genolve-video/",$url)>0 ){
			$validLink = true;
			}
		else {
			genolve_send_json_error("the link is bad:".$url);
			}
		////echo "\ngenolve_savefile try to save extension:".$ext. " url:".$url." validLink:".$validLink;
		if( $validLink == true ){
			$timeout = 300; //get_option( 'emu_timeout' , 300 );
			// DOWN LOAD  IMG                                 DOWN LOAD  IMG                         DOWN LOAD  IMG
			$tmp = download_url( $url , $timeout );
			// on windows, expect: C:\WINDOWS\TEMP/options-general-7af816c6-7ade-4385-d7b6-af74927229c3-bjKljh.tmp
			////echo "genolve_savefile I downloaded your stuff here:".$tmp;
			if ( is_wp_error( $tmp ) ) { // ERROR  CATCH 1
				unlink($tmp);
				genolve_send_json_error( $tmp->get_error_message() );
				}
			/* WAY to directly put in directory
			(wont see in media)
			
			 see if we have the uploads dir
			$dirO = wp_upload_dir();
			$uploads_dir = trailingslashit( $dirO['basedir'] ) . 'genolve-uploads';
			wp_mkdir_p( $uploads_dir );  // no prob to call if already exists
			
			// move instead? rename('foo/test.php', 'bar/test.php');
			$target = trailingslashit($uploads_dir).$randname;
			////echo "\ngenolve_savefile target file:".$target;
			// for a raw copy copy($tmp,$target);
			*/
			// SIDE LOAD                                   SIDE LOAD                          SIDE LOAD
			$fileA=array(
					'name' => $randname, 
				// not in codex example https://codex.wordpress.org/Function_Reference/media_handle_sideload
				//  'type' => 'image/jpeg', 
					'type' => wp_check_filetype($tmp),
					'tmp_name' => $tmp, 
					'error' => 0, //normally, this is used to store an error, should the upload fail. but since this isnt actually an instance of $_FILES we can default it to zero here
					'size' => filesize($tmp) );
			$new_post_id= ($pid==null || $pid<0)?0:$pid; // set 0 for no parent post id or simple attachment otherwise pass post id for include in post
			$media = media_handle_sideload($fileA, $new_post_id, $desc );  // <    M E D I A    S I D E     L O A D
			
			if (  is_wp_error( $media ) ) {// ERROR  CATCH 2
				unlink($tmp);
				genolve_send_json_error( $media->get_error_message() );
			} else if(empty($media) ) {		// ERROR  CATCH 3
				unlink($tmp);
				genolve_send_json_error('the function media_handle_sideload reported success but failed!');
				}
			else {  // SUCCESS    process image into MEDIA FOLDER
				unlink($tmp);
				// for a video icon i think we'd need:
				//    side load the jpg cover seperate and pass THAT in as the media
				// https://gist.github.com/zagk/000a56d9b17a853bba2c4599e37a82e2
				$data = set_post_thumbnail( $new_post_id, $media );

				$local_url = wp_get_attachment_url( $media );
				$local_fname = preg_replace("/.*\//","",$local_url);
				$dmsg .="local_fname:".$local_fname." code:".$cod;
				if($themode == "justimg")
					;//nada
				else{
					// UPDATE IMAGE ARRAY
					// get current list
					$genolve_img_sel=get_option("genolve_img_sel");
					$genolve_img_val=get_option("genolve_img_val");
					$genolve_img_par=get_option("genolve_img_par");
					if (gettype($genolve_img_sel) != "array") {
						$genolve_img_sel=array();
						$genolve_img_val=array();
						$genolve_img_par=array();
						}
					// WILL ALWAYS be NEW
					array_push($genolve_img_sel,$local_fname); // image name
					array_push($genolve_img_val,$cod); // the "code"
					array_push($genolve_img_par,wp_json_encode(array('date'=>date("Ymd")))); // only db entries after SEO update have date for path in media lib
					$dmsg .=" genolve_img_sel type:".gettype($genolve_img_sel)." val:".implode(",",$genolve_img_sel)." genolve_img_val:".implode(",",$genolve_img_val);
					update_option("genolve_img_sel",$genolve_img_sel);
					update_option("genolve_img_val",$genolve_img_val);
					update_option("genolve_img_par",$genolve_img_par);
					}
				// PREPARE JSON MSG
				$jsonRespA=array('result' => 'success', 
								'message' => 'Your file has been placed here:'.$local_url.'<br><img src="'.$local_url.'" width="300px" height="auto" />', 
								'localurl' => $local_url,
								'origurl' => $origurl,
								'slot' => $theslot,
								'key' => $thekey,
								'debug' => $dmsg,
								'success' => true,
								'beyonce_customize' => wp_create_nonce( 'beyonce_customize' )   );
				echo json_encode( $jsonRespA );	
				wp_die();
			}
			// END SIDE LOAD                                   SIDE LOAD                          SIDE LOAD
			
			}
		wp_die();
	}// end genolve_savefile
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 genolve_loadCSS -Function to register and then enqueue CSS and fonts on the admin settings page
 called by settings->genolve_adminMenu
*/
function genolve_loadCSS() {
	wp_enqueue_style('genolve_settingsCSS', GENOLVE_PLUGIN_DIR.'css/genolve-settings.css', __FILE__, '', 'all');	
	add_action('admin_init', 'genolve_addHeaderCode');
	}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 
   genolve_add_meta_tags - 202307 needed for firefox, cross-origin complaints
	 wrong: HTTP-EQUIV="Access-Control-Allow-Origin" content="https://www.genolve.com/"
	 "Content-Security-Policy" blocks too much
  
	function genolve_add_meta_tags() {
    echo '<meta HTTP-EQUIV="Content-Security-Policy" content="script-src  \'self\' \'unsafe-inline\' www.genolve.com cdn.jsdelivr.net pixabay.com;" />';
	}
	add_action( 'admin_head', 'genolve_add_meta_tags',10);
	*/
/**
 * Add button size class.
 *
 * @param  string $block_content Block content to be rendered.
 * @param  array  $block         Block attributes.
 * @return string
 input example: <figure class="wp-block-image is-resized has-spacing-large has-custom-attribute" style="margin-bottom:30px"><img src="http://localhost/wp-content/uploads/2016/02/library-1024x678.jpg" alt="" class="wp-image-421" width="659" height="436"/></figure>
 */
function add_image_block_url( $block_content = '', $block = [] ) {
  if ( isset( $block['blockName'] ) && 'core/image' === $block['blockName'] ) {
    $defaults = ['size' => 'regular'];
    $args = wp_parse_args( $block['attrs'], $defaults );
		//echo 'RENDERIMAGE:'.$block_content;
    /**/
		$html = str_replace(
      '<img src=',
      '<img  data-gnlv="hey" src=',
      $block_content
    );

    return $html;
}
  return $block_content;
}

add_filter( 'render_block', 'add_image_block_url', 10, 2 );

/**
 * genolve_user_profile_fields - add credit limit to user profile
 *
 * @param  string $hook          Hook name.
 * @param  string $funcname      Name of function.
 * @return none
 */
//$rsel= get_option('genolve_reseller'); //
$rsel= (get_option('genolve_credits_mode')=="credoff") ? FALSE:TRUE;
if($rsel==TRUE){
	add_action( 'show_user_profile', 'genolve_user_profile_fields' );
	add_action( 'edit_user_profile', 'genolve_user_profile_fields' );
	}
//helper function
function is_site_admin(){
  return in_array('administrator',  wp_get_current_user()->roles);
	}
	
function genolve_user_profile_fields( $user ) { 
		$enableinput = is_site_admin()?"":"readonly";
		$curlimit    = esc_attr( get_the_author_meta( 'genolve_credlimit', $user->ID ) );
		$col_lbl     = get_option("genolve_credits_mode")=="credlimit"?"Monthly AI Credit Limit":"AI Credits";
		if($curlimit === ""){// default to a high value
			/* 20251211 blank, the default, means global credit pool
			$curlimit    = 5000;
			update_user_meta( $user->ID, 'genolve_credlimit', $curlimit );
			*/
			}
		?>
    <br><h3><?php _e("Genolve ".$col_lbl, "blank"); ?></h3>

    <table class="form-table">
    <tr>
        <th><label for="genolve_credlimit"><?php _e($col_lbl); ?></label></th>
        <td>
            <input type="text" name="genolve_credlimit" id="genolve_credlimit" <?php echo $enableinput?> value="<?php echo $curlimit ?>" class="regular-text" /><br />
            <span class="description"><?php 
						if(get_option("genolve_credits_mode")=="credlimit")
						_e("Enter an integer, e.g. 1000 for $10 credit limit, 0 to disable, blank to share global credit pool.<br>Only the Administrator can change this. Unused credits expire."); 
						else
						_e("Enter an integer, e.g. 1000 for $10 credit, 0 to disable, blank to share global credit pool.<br>Only the Administrator can change this.");
						?></span>
        </td>
    </tr>
   
    </table>
    <?php 
} // end genolve_user_profile_fields

/**
 * genolve_save_user_profile_fields - on form submit, save meta data (ai credit limit)
 *
 * @param  string $hook          Hook name.
 * @param  string $funcname      Name of function.
 * @return none
 */
if($rsel==TRUE){
	add_action( 'personal_options_update',  'genolve_save_user_profile_fields' );
	add_action( 'edit_user_profile_update', 'genolve_save_user_profile_fields' );
	}

function genolve_save_user_profile_fields( $user_id ) {
    if ( empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'update-user_' . $user_id ) ) {
        return;
    }
    
    if ( !current_user_can( 'edit_user', $user_id ) ) { 
        return false; 
    }
    update_user_meta( $user_id, 'genolve_credlimit', $_POST['genolve_credlimit']===""?"":abs(intval($_POST['genolve_credlimit'])) );
} //  end genolve_save_user_profile_fields

/**
 * genolve_manage_users_columns - add a column to the user screen options list
 *
 * @param  string $columns       columns array
 * @return none
 */
function genolve_manage_users_columns( $columns ) {
    // 'custom_field_key' is the unique slug for your column
    // 'Custom Field Label' is the name that appears in the admin header and Screen Options
		$col_lbl = get_option("genolve_credits_mode")=="credlimit"?"AI Credit Limit":"AI Credits";
    $columns['genolve_credlimit'] = esc_html__( $col_lbl, 'text_domain' );
    return $columns;
}
if($rsel==TRUE)
	add_filter( 'manage_users_columns', 'genolve_manage_users_columns' );
/**
 * genolve_manage_users_custom_column - display in user summary table: genolve credit limit
 *
 * @param  string $columns       columns array
 * @return none
 */
function genolve_manage_users_custom_column( $output, $column_key, $user_id ) {
    if ( 'genolve_credlimit' === $column_key ) {
        // Retrieve the user meta value
        $value = get_user_meta( $user_id, 'genolve_credlimit', true );
        // Display the value, or '-' if empty
        $output = $value=="" ? '-':$value;
    }
    return $output;
}
if($rsel==TRUE)
	add_filter( 'manage_users_custom_column', 'genolve_manage_users_custom_column', 10, 3 );

/**
 * genolve_initialise_user_meta -Initialize default user meta when a new user is registered.
 *
 * @param int $user_id ID for the user who has registered.
 */
function genolve_initialise_user_meta( $user_id ) {
    // Use update_user_meta() to add or update the meta field
    update_user_meta(
        $user_id,          // The user ID
        'genolve_credlimit',  // The meta key 
        get_option("genolve_start_credits")    // The selected value (initial value)
    );
}
if($rsel==TRUE)
	add_action( 'user_register', 'genolve_initialise_user_meta', 10, 1 );

/**
 * genolve_update_user_meta_after_woo_purchase - Automatic update of credits metadata after a WooCommerce purchase.
 *
 * @param int $order_id ID for the order completed.
 */
add_action( 'woocommerce_payment_complete', 'genolve_update_user_meta_after_woo_purchase' );
// because adding to value, have to choose one
//add_action( 'woocommerce_order_status_completed', 'genolve_update_user_meta_after_woo_purchase' );

function genolve_update_user_meta_after_woo_purchase( $order_id ) {
    // Get the order object
    $order = wc_get_order( $order_id );

    // Get the user ID associated with the order
    $user_id = $order->get_user_id();
		// Get all order items
    $items = $order->get_items();
		$order_currency = $order->get_currency();
		$havexc = is_plugin_active( 'currency-switcher-woocommerce/currency-switcher-woocommerce.php' );
    if ( empty( $items ) ) {
        //echo '<p>No items found for this order.</p>';
        return;
    }

    // Loop through each order item
    foreach ( $items as $item_id => $item ) {
        // Get the product object for the order item
        $product = $item->get_product();

        if ( $product ) {
            // Get the SKU
            $sku = $product->get_sku();
						
						if($sku && preg_match("/^genolve_/i",$sku) ){
							// Get the price (unit price, excluding tax in this case, see notes below)
							// You can also use $item->get_subtotal() for the line subtotal or $item->get_total() for the line total after discounts
							$price = $item->get_subtotal();// this accounts for quantity 
							error_log( "genolve woo START with user: $user_id, price: $price, currency: $order_currency have currency-switcher?:".$havexc);
							// Check if the order currency is different from the base currency
							if ( $order_currency !== "USD" && $havexc) {
								//                 from     to
								$price = xc_price( $order_currency, 'USD', $price );
								error_log( "genolve woo convert to USD price: $price");
								}
							$credits = round(floatval($price)*100);
						 	// Check if a user is associated with the order and is a registered user (not a guest)
							if ( $user_id && $user_id > 0 ) {
									if(get_option("genolve_credits_mode")=="credlimit")
										$meta_value = $credits;
									else{ //increment
										$curlimit  = intval(get_the_author_meta( 'genolve_credlimit', $user_id )) ; // CREDITS BALANCE
										$meta_value = $curlimit + $credits;
										}
									// Update the user metadata field
									update_user_meta( $user_id, 'genolve_credlimit', $meta_value );
							} // end userid
						}// end sku
       	 }// end product
    	}// end for
		}// end func genolve_update_user_meta_after_woo_purchase

/**
 * genolve_update_user_meta_after_easycart_purchase - Automatic update of credits metadata after an EasyCart purchase.
 *
 * @param int $order_id ID for the order completed.
 */
add_action( 'wpeasycart_order_paid', 'genolve_update_user_meta_after_easycart_purchase',10,1 );
// because adding to value, have to choose one
//add_action( 'woocommerce_order_status_completed', 'genolve_update_user_meta_after_woo_purchase' );

function genolve_update_user_meta_after_easycart_purchase( $order_id ) {

		// not working: $order = wpeasycart_get_order_by_id( $order_id );

    // Get the user ID associated with the order
		$db_admin = new ec_db_admin();
		$order = $db_admin->get_order_row_admin( $order_id );
		// not working $user_id = $order->user_id;
		$tmpuser = wp_get_current_user();
		$user_id = $tmpuser->ID;
		error_log( "genolve easycart START hook with order_id: $order_id  got user?".$user_id." got order obj?".gettype($order) );
		if( $order ) {				
				$order_details = $db_admin->get_order_details_admin( $order_id );
				
				// $order_details = ec_db::get_order_details( $order_id, $user_id );
				foreach( $order_details as $item ) {
						//not defined $sku = $item->sku;
						$sku = $item->model_number;
						$quantity = $item->quantity;
						$unit_price = $item->unit_price;
						$total_price = $item->total_price;
						error_log( "genolve easycart ITEM model: $sku QTY: $quantity total_price: $total_price");
						if($sku && $total_price && preg_match("/^genolve_/i",$sku) ){
							$credits = round(floatval($total_price)*100);
						 	// Check if a user is associated with the order and is a registered user (not a guest)
							if ( $user_id && $user_id > 0 ) {
									if(get_option("genolve_credits_mode")=="credlimit")
										$meta_value = $credits;
									else{ //increment
										$curlimit  = intval(get_the_author_meta( 'genolve_credlimit', $user_id )) ; // CREDITS BALANCE
										$meta_value = $curlimit + $credits;
										}
									// Update the user metadata field
									update_user_meta( $user_id, 'genolve_credlimit', $meta_value );
							} // end userid
						}// end sku
					}// end foreach
				}// end order
		

    /* hallucinations
		    // Get the order object
    $order = new ec_order( $order_id );
		// Get all order items
    $items = $order->items; // alternate: $order->get_items();
    if ( empty( $items ) ) {
        //echo '<p>No items found for this order.</p>';
        return;
    }
    foreach ( $items as  $item ) {
       
            // Get the SKU
            $sku = $item->sku;
						$qty = $item->qty;
						$price = (float) $item->price_with_options; 
						if(!$price)
							$price = (float) $item->price;// Or $item->price
            // If you need the total item price:
            if(!$price)
							$price = (float) $item->total_price_with_options;
						if($sku && $price && preg_match("/^genolve_/i",$sku) ){
							$credits = round(floatval($price)*100);
						 	// Check if a user is associated with the order and is a registered user (not a guest)
							if ( $user_id && $user_id > 0 ) {
									if(get_option("genolve_credits_mode")=="credlimit")
										$meta_value = $credits;
									else{ //increment
										$curlimit  = intval(get_the_author_meta( 'genolve_credlimit', $user_id )) ; // CREDITS BALANCE
										$meta_value = $curlimit + $credits;
										}
									// Update the user metadata field
									update_user_meta( $user_id, 'genolve_credlimit', $meta_value );
							} // end userid
						}// end sku
    	}// end for
			*/
		}// end func genolve_update_user_meta_after_easycart_purchase
/**
 * Convert price from one currency to another.
 *
 * @param string $from_currency ISO currency code (e.g., 'USD', 'EUR', 'GBP')
 * @param string $to_currency   ISO currency code (e.g., 'USD', 'EUR', 'GBP')
 * @param float  $price        Price to convert
 * @param bool   $apply_rounding Optional. Whether to apply plugin's rounding/pretty price settings. Default true.
 * @return float Converted price
 */
if ( ! function_exists( 'xc_price' ) ) {
	function xc_price( $from_currency, $to_currency, $price, $apply_rounding = true ) {
		
		// Validate inputs
		if ( empty( $from_currency ) || empty( $to_currency ) ) {
			return $price;
		}
		//if(! is_numeric( $price ))
		$price = floatval($price);
		// Normalize currency codes to uppercase
		$from_currency = strtoupper( $from_currency );
		$to_currency   = strtoupper( $to_currency );
		
		// If same currency, return price as-is
		if ( $from_currency === $to_currency ) {
			return  $price;
		}
		
		// currency switcher woocommerce
		// This function handles all exchange rate sources (ECB, Coinbase, etc.)
		$exchange_rate = alg_wc_cs_get_exchange_rate( $from_currency, $to_currency );
		
		// If exchange rate is 0 or invalid, return original price
		if ( 0 == $exchange_rate || false === $exchange_rate ) {
			return  $price;
		}
		
		// Convert the price
		$converted_price =  $price * floatval( $exchange_rate );
		
		// Apply plugin's rounding and pretty price settings if requested
		if ( $apply_rounding && function_exists( 'alg_wc_cs_round_and_pretty' ) ) {
			$converted_price = alg_wc_cs_round_and_pretty( $converted_price, $to_currency );
		}
		
		return $converted_price;
	}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* START debug prints, production: comment out 

define('temp_file', ABSPATH.'/_temp_out.txt' );

add_action("activated_plugin", "activation_handler1");
function activation_handler1(){
    $cont = ob_get_contents();
    if(!empty($cont)) file_put_contents(temp_file, $cont );
}

add_action( "pre_current_active_plugins", "pre_output1" );
function pre_output1($action){
    if(is_admin() && file_exists(temp_file))
    {
        $cont= file_get_contents(temp_file);
        if(!empty($cont))
        {
            echo '<div class="error"> Error Message:' . $cont . '</div>';
            @unlink(temp_file);
        }
    }
}
 END debug prints, production: comment out */
?>
