<?php 

// The methods here are accessible only by using `dashboard::call()` method;

defined( 'DASHBOARD_MOD_DIR' ) or DIE;

// Ensure that is file is called from the right source!

try {
	if( self::class_name !== dashboard::class_name ) 
		exit( 'Access to built-in closure from unrecognized class' );
} catch( Error $e ) {
	exit( 'Access to built-in closures failed!' );
};

// ---------------------- < FUNCTION BREAK > --------------------



self::$calls['PHPMailer'] = function( bool $throwException = false ) {
	
	$PHPMailer = new \PHPMailer\PHPMailer\PHPMailer( $throwException );
	$PHPMailer->isHTML(true);
	$PHPMailer->CharSet = 'utf-8';
		
	$options = uss::$global['options'];
	
	if( $options->get('smtp:state') === 'custom' ) {
		$PHPMailer->isSMTP();
		$PHPMailer->SMTPDebug = 0;
		$PHPMailer->SMTPAuth = true;
		$PHPMailer->SMTPSecure = $options->get('smtp:security');
		$PHPMailer->Host = $options->get('smtp:server');
		$PHPMailer->Username = $options->get('smtp:username');
		$PHPMailer->Password = $options->get('smtp:password');
		$PHPMailer->Port = (int)$options->get('smtp:port');
	};
	
	$sender =  $options->get('email:from');
	if( empty($sender) ) $sender = $options->get('email:admin');
	
	$PHPMailer->setFrom( $sender, $options->get('site:title') );
	
	return $PHPMailer;
	
};



// ---------------------- < FUNCTION BREAK > --------------------



self::$calls['email:confirm_user_email'] = function( string $new_email, ?string $old_email = null ) {
	
	/*
		GET USER BY EMAIL
		------------------
		We're either adding a new email that needs confirmation: OR
		We're updating an old email and the new email needs confirmation
		
		Hence, if $old_email is supplied, get user by old email
		else, get user by new email
	*/
	
	$prefix = DB_TABLE_PREFIX;
	$user = dashboard::fetch_assoc( "{$prefix}_users", $old_email ?? $new_email, 'email' );
	if( !$user ) return false;
	
	
	/* 
		GENERATE CONFIRMATION CODE & LINK;
		----------------------------------
		If: 
			- The email is absolutely new, then confirmation key becomes v-code! ( verification - code )
		else:
			- The confirmation key becomes `v-code:update`
			
			- Followed by `v-code:email` which saves the new email that will be updated on confirmation
			
	*/
	
	if( empty($old_email) ) {
		
		$pallet = array( "v-code" => core::keygen(20) );
		
		$encoding = base64_encode( "new:{$pallet['v-code']}:{$user['email']}" );
		
	} else {	
	
		$pallet = array(
			"v-code:update" => core::keygen(20),
			"v-code:email" => $new_email
		);
		
		$encoding = base64_encode( "update:{$pallet['v-code:update']}:{$user['email']}" );
	
	};
	
	/*
		Load the information into the user meta!
	*/
	
	foreach( $pallet as $_key => $_value ) {
		uss::$global['usermeta']->set( $_key, $_value, $user['id'] );
	};
	
	/*
		Generate confirmation link URL
	*/
	
	$v_url = core::url( ROOT_DIR . '/' . DASHBOARD_FOCUS_URI . "?v={$encoding}" );
	
	/*
		X2Client Library makes email template creation more easier
		
		@https://github.com/ucscode/X2Client
	*/
	
	$maildir = DASHBOARD_MOD_DIR . "/view/MAIL/";
	
	// Get the email Template!
	$template = require ( $maildir . "/template.php" );
	
	// Get the email message!
	$message = require ( $maildir . ( !$old_email ? "/confirm-email.php" : "/reconfirm-email.php" ) );
	
	
	/*
		Convert the Code into HTML Table For Multiple Email Client Compactibility
	*/
	
	$x2client = new X2Client( $message );
	$message = $x2client->render( "body > table" );
	
	
	// replace variables inside the email message;
	
	$message = core::replace_var( $message, array(
		'email' => $new_email,
		'href' => $v_url
	));
	
	
	// replace variables inside the email template
	
	$__body = core::replace_var( $template, array( 
		'content' => $message,
		'footer' => "You are receiving this email because you signup up at " . uss::$global['title']
	) );
		
	// Prepare Email;
	
	$PHPMailer = dashboard::call('PHPMailer');
	
	$PHPMailer->addAddress( $new_email );
	$PHPMailer->Subject = $info['subject'] ?? 'Verify Your Email';
	$PHPMailer->Body = $__body;
	
	// Send it!
	
	return $PHPMailer->send();
	
};



// --------------------- < FUNCTION BREAK > -------------------------



self::$calls['email:send_reset_email'] = function( $email ) {
	
	
	// Get the associated account;
	
	$prefix = DB_TABLE_PREFIX;
	$user = dashboard::fetch_assoc( "{$prefix}_users", $email, 'email' );
	if( !$user ) return false;
	
	
	// Generate the reset code;
	
	$r_code = core::keygen( 15 );
	
	uss::$global['usermeta']->set( "r-code", $r_code , $user['id'] );
	
	
	// Generete the reset link;
	
	$encode = base64_encode( "{$r_code}:{$user['email']}:" . time() );
	
	$r_url = core::url( ROOT_DIR . '/' . DASHBOARD_FOCUS_URI . "/reset?v={$encode}" );
	
	
	/*
		Get the template Messages;
	*/
	
	$maildir = DASHBOARD_MOD_DIR . "/view/MAIL/";
	
	$template = require ( $maildir . "/template.php" );
	$message = require ( $maildir . "/reset-email.php" );
	
	$x2client = new X2Client( $message );
	$message = $x2client->render( 'body > table' );
	
	
	/*
		
	*/
	
	$message = core::replace_var( $message, array(
		"href" => $r_url
	));
	
	$__body = core::replace_var( $template, array(
		"content" => $message,
		"footer" => 'Secure you account and stay safe!'
	));
	
	// Send the reset password email;
	
	$PHPMailer = dashboard::call( "PHPMailer" );
	$PHPMailer->addAddress( $user['email'] );
	$PHPMailer->Subject = "Reset Account Password";
	$PHPMailer->Body = $__body;
	
	return $PHPMailer->send();
	
};



// --------------------- < FUNCTION BREAK > -------------------------



self::$calls['upload_image'] = function( array $file, string $folder ) {
	
	if( !empty($file['error']) ) return;
	
	$size = $file['size'] / pow( 1024, 2 ); // kilobyte
	if( $size > 2.5 ) throw new Exception( "Image size should not be greater than 2.5 MegaByte" );
	
	$image = getimagesize($file['tmp_name']);
	if( !$image ) throw new Exception( "The uploaded file is not accepted" );
	
	$format = pathinfo( $file['name'], PATHINFO_EXTENSION );
	$extensions =  [ 'jpg', 'png', 'gif', 'jpeg', 'webp' ];
	
	if( !in_array( $format, $extensions ) ) {
		throw new Exception( "Invalid Format: Only " . implode( ", ", $extensions ) . " are allowed" );
	};
	
	// dashboard image directory;
	$img_dir = DASHBOARD_MOD_DIR . "/assets/images";
	
	// create folder if not exists;
	$img_folder = $img_dir . "/{$folder}";
	if( !is_dir($img_folder) ) mkdir( $img_folder );
	
	// name the file;
	$img_name = "{$folder}/" . sha1( $folder . uniqid() . $file['name'] ) . ".{$format}";
	
	// destination;
	
	$fullpath = "{$img_dir}/{$img_name}";
	
	$moved = move_uploaded_file( $file['tmp_name'], $fullpath );
	
	if( $moved ) return $img_name;
	
};



// --------------------- < FUNCTION BREAK > ----------------------



self::$calls['user:avatar'] = function( ?int $userid = null ) {
	
	if( empty($userid) ) $userid = uss::$global['user']['id'];
	
	$avatar = uss::$global['usermeta']->get('avatar', $userid);
	if( !$avatar ) $avatar = 'user.png';
	
	$avatar = core::url( DASHBOARD_MOD_DIR . "/assets/images/{$avatar}" );
	
	return $avatar;
	
};



// --------------------- < FUNCTION BREAK > ------------------



self::$calls['form:prevent-resubmit'] = function() {
	/*
		This close method will prevent browser from displaying form resubmission message
		when a user reloads the page;
		-------------- () ------------- () -------------- () ------------------ () -----------
		- The page that you're looking for used information that you entered. 
		- Returning to that page might cause any action you took to be repeated. 
		- Do you want to continue?
	*/
	events::addListener('@body::after', function() { ?>
		<script>
			if ( window.history.replaceState ) {
				window.history.replaceState( null, null, window.location.href );
			};
		</script>
<?php });
};



// -------------------- < FUNCTION BREAK > --------------------



self::$calls['empty:no-result'] = function( $func = 'Try searching with a different filter' ) { ?>
	<div class='text-center py-4 empty-state'>
		<h1 class='mb-3 fw-semibold'>No Result</h1>
		<img src='<?php echo core::url( DASHBOARD_MOD_DIR . '/assets/images/no-result.png' ); ?>' width='90px'>
		<div class='p-4'>
			<?php 
				if( is_callable($func) ) $func();
				else if( !is_object($func) && !is_array($func) ) echo $func; 
			?>
		</div>
	</div>
<?php };



// ------------------- < FUNCTION BREAK > ---------------------



self::$calls['user:delete'] = function( int $userid ) {
	$prefix = DB_TABLE_PREFIX;
	$SQLS = [
		"DELETE FROM {$prefix}_users WHERE id = {$userid}"
	];
	foreach( $SQLS as $SQL ) {
		/* 
			The last SQL query is what really matters;
			The others are just to remove insignificant records after the user has been removed;
		*/
		$deleted = uss::$global['mysqli']->query( $SQL );
	};
	return $deleted;
};



// --------------------- < FUNCTION BREAK > --------------------



self::$calls['site:__vars'] = function() {
	foreach( ['title', 'tagline', 'description', 'icon'] as $key ) {
		$value = uss::$global['options']->get( "site:{$key}" );
		if( !empty($value) ) {
			if( $key == 'icon' ) $value = core::url( DASHBOARD_MOD_DIR . "/assets/images/{$value}" );
			uss::$global[ $key ] = $value;
		};
	};
};


// -------------------- < FUNCTION BREAK > -----------------------


self::$calls['color'] = function( ?string $name ) {
	switch( strtolower(trim($name)) ) {
		case 'open':
			return 'primary';
		case 'closed':
		case 'cancelled':
			return 'danger';
		case 'resolved':
			return 'success';
	};
};


// -------------------- < FUNCTION BREAK > -------------------------


self::$calls['user:get-sponsor'] = function( string $key = 'ref' ) {
	$usercode = $_GET[ $key ] ?? null;
	if( !$usercode ) {
		$usercode = $_COOKIE['ussref'] ?? null;
		if( !$usercode ) return;
	};
	$prefix = DB_TABLE_PREFIX;
	$sponsor = dashboard::fetch_assoc("{$prefix}_users", $usercode, "usercode");
	if( $sponsor && !headers_sent() ) {
		/*
			This will save sponsor in cookie for 30 days!
			Hence, when the user comes again to register even without a referral link,
			The system is locate the sponsor automatically
		*/
		setcookie( 'ussref', $usercode, (time() + (86400 * 30)), '/' );
	};
	return $sponsor;
};


// -------------------- < FUNCTION BREAK > --------------------------



