<?php

// Send email using the phpMailer class

namespace modules\emailPhpMailer;

	$dir = __DIR__ . '/src';
	require_once "$dir/Exception.php";
	require_once "$dir/SMTP.php";
	require_once "$dir/PHPMailer.php";

class phpmailer2 extends \PHPMailer\PHPMailer\PHPMailer {
	public $MIMEHeader;
	public $MIMEBody;
}

class main extends \moduleMain {

	use \modules\config\traits {
			\modules\config\traits::__construct as __ConstructConfig;
		}

	public function __construct() {
		parent::__construct(__DIR__);
		$this->__ConstructConfig();
	}

	public function Activate() {
		
		hook_add('email.send', [$this, '__send']);
		hook_add('email.transform', [$this, '__effect']);		// temp
		hook_add('email.prepare', [$this, '__prepare']);		// like send, but only creates the email/mime body - does not send
	}
	
	
	public function __effect(&$mailobject) {		 // bold, italic, hollow
		if (is_object($mailobject)) {
//			$mailobject->Subject($this->transform($mailobject->Subject(), 0x1D400, 0x1D41A, 0x1D7CE));				// bold
//			$mailobject->Subject($this->transform($mailobject->Subject(), 0x1D538, 0x1D552, 0x1D728));		// double strike
			
		}
	}

	// http://xahlee.info/comp/unicode_math_font.html
	public function transform($text, $delta_uppercase, $delta_lowercase, $delta_numeric) {
		$result = '';
		for($i = 0; $i < strlen($text); $i++) {
			$ch = $text[$i];
			if (($p = strpos('CHNPQRZ', $ch)) !== FALSE && $delta_uppercase == 0x1D538) {
				$result .= $this->_utf8($this->_exception($p));
			} elseif ($ch >= 'A' && $ch <= 'Z') {
				$result .= $this->_utf8($delta_uppercase + ord($ch) - 65);
			} elseif ($ch >= 'a' && $ch <= 'z') {
				$result .= $this->_utf8($delta_lowercase + ord($ch) - 97);
			} elseif ($ch >= '0' && $ch <= '9') {
				$result .= $this->_utf8($delta_numeric + ord($ch) - 48);
			} else {
				$result .= $ch;
			}
		}
		return $result;
	}

	// characters that are out of place in the ut8 table:
	private function _exception($p) {
		$exceptions = [8450, 8461, 8469, 8473, 8474, 8477, 8484];
		return $exceptions[$p];
	}
	

	private function _utf8($num) {
		if($num<=0x7F)       return chr($num);
		if($num<=0x7FF)      return chr(($num>>6)+192).chr(($num&63)+128);
		if($num<=0xFFFF)     return chr(($num>>12)+224).chr((($num>>6)&63)+128).chr(($num&63)+128);
		if($num<=0x1FFFFF)   return chr(($num>>18)+240).chr((($num>>12)&63)+128).chr((($num>>6)&63)+128).chr(($num&63)+128);
		return '';
	}
	
	private function subjectEncode($subject) {
		$subject = base64_encode(utf8_encode($subject));
		return '=?UTF-8?B?' . $subject . '?=';
	}
	
	private function _prepare($mailobject) {
		//$p = new \PHPMailer\PHPMailer\PHPMailer;
		$p = new phpmailer2;
//			$p->SMTPDebug = 4;
		$p->Timeout = 30;
		$p->CharSet =\PHPMailer\PHPMailer\PHPMailer::CHARSET_UTF8;
		$p->Encoding = \PHPMailer\PHPMailer\PHPMailer::ENCODING_QUOTED_PRINTABLE;
		
		if (!empty($this->settings['smtp'])) {
			$p->Mailer = 'smtp';
			$host = $this->settings['smtp'];
			switch($this->settings['port']) {
				case 25:
					break;
				case 465:
					$host = 'ssl://' . $host . ':465';
					$p->SMTPSecure = 'ssl';
					break;
				case 466:
					$host = 'tls://' . $host . ':466';		// needs valid webserver cert installed in mail server
					$p->SMTPSecure = 'tls';
					break;
				case 587:
					$host = 'tls://' . $host . ':587';
					$p->SMTPSecure = 'tls';
					break;
			}
			$p->Host = $host;
			$p->SMTPAuth = TRUE;
			$p->Username = $this->settings['user'];
			$p->Password = $this->settings['pass'];
		}

		$count = 0;
		foreach($mailobject->to() as $item) {
			if ($item['name'] == '') {
				$p->addAddress($item['email']);
			} else {
				$p->addAddress($item['email'], $item['name']);
			}
			$count++;
		}
		
		foreach($mailobject->cc() as $item) {
			if ($item['name'] == '') {
				$p->addCC($item['email']);
			} else {
				$p->addCC($item['email'], $item['name']);
			}
			$count++;
		}
		foreach($mailobject->bcc() as $item) {
			if ($item['name'] == '') {
				$p->addBCC($item['email']);
			} else {
				$p->addBCC($item['email'], $item['name']);
			}
			$count++;
		}
		foreach($mailobject->from() as $item) {
			$p->setFrom($item['email']);
			$name = $item['name'] ?? '';
			if ($name != '') {
				$p->FromName = $name;
			}
			break;
		}
		
		foreach($mailobject->ReplyTo() as $item) {
			if ($item['name'] == '') {
				$p->addReplyTo($item['email']);
			} else {
				$p->addReplyTo($item['email'], $item['name']);
			}
		}
		
		if (!$count) {
			return "No destination specified for email";
		}
		
		$headers = $mailobject->Headers();
		$p->clearCustomHeaders();
		foreach($headers as $item) {
			$p->addCustomHeader($item['key'], $item['value']);
		}

		$images = $mailobject->getImages();
		foreach($images as $id => $image) {
			$finfo = new \finfo(FILEINFO_MIME_TYPE);
			$mimeType = $finfo->buffer($image['image']);
			if ($image['disposition'] == 'inline') {
				$p->addStringEmbeddedImage($image['image'], $id, $image['name'] ?? '', 'base64', $mimeType); 
			} else {
				$p->addStringAttachment($image['image'], $image['name'] ?? '', 'base64', $mimeType); 
			}
		}
		
		$p->Body = $mailobject->body();			// html
		$p->AltBody = $mailobject->text();		// text
		$p->isHTML(true);
		$p->Subject = $mailobject->subject();
		$p->XMailer = ' ';      // no X-Mailer header
		return $p;
	}
	
	public function __send(&$result, $mailobject) {
		if ($result === NULL) {
		
			$settings = $this->SettingGet('config.module_info', NULL);
            
			if (isset($settings['replyto'])) {
	            $c = count($mailobject->ReplyTo() ?? []);
	            if (!$c && isset($settings['replyto'])) {
	                $mailobject->ReplyTo($settings['replyto']);
	            }
			}

			$p = $this->_prepare($mailobject);
			if (is_string($p)) {		// an error has occurred
				$result = $p;
				return;
			}

			if (!$p->Send()) {
				//$result = TRUE;
				$result = $p->ErrorInfo;
				error_log('Sendmail: ' . $result);
//				echo "Mail was not sent, error is: " . $p->ErrorInfo;
			} else {
                $result = FALSE;
//				echo "email sent";
			}
		}
	}
	
	public function __prepare(&$result, $mailobject) {
		if ($result === NULL) {
			hook_execute('email.transform', $mailobject);		// compile templates
			$p = $this->_prepare($mailobject);
			if (is_string($p)) {
				$result = [
					'error'		=> $p,
				];
			} else {
				$p->Mailer = 'smtp';
				$p->preSend();
				$result = [
					'headers'	=> $p->MIMEHeader,
					'body' 		=> $p->MIMEBody,
				];
			}
		}
	}

}
