<?php

class ParTCP_Incoming_Message {

	public $signatureStatus;
	public $signatureStatusMessage;
	public $data;
	public $rawMessage;
	public $senderPubKey;
	public $encryptedElements = [];
	private $crypto; // an object providing crypto functions
	private $keyRetrievalFunction; // callback for retrieving public key of an identity


	public function __construct( $rawMessage, $cryptoObject, $keyRetrievalFunction = NULL ){
		$this->crypto = $cryptoObject;
		$this->keyRetrievalFunction = $keyRetrievalFunction;
		$this->rawMessage = str_replace( ["\r\n", "\r"], "\n", trim( $rawMessage ) );
		$this->data = yaml_parse( $this->rawMessage );
		var_dump( $this->data );
		if ( ! $this->data ){
			return;
		}
		$senderKey = $this->get_sender_key( TRUE );
		if ( ! $senderKey ){
			return;
		}
		foreach ( $this->data as $key => $value ){
			if ( substr( $key, -1 ) == '~' ){
				$key = substr( $key, 0, -1 );
				$this->encryptedElements[] = $key;
				$decrypted = $this->crypto->decrypt( $value, $senderKey );
				if ( $decrypted !== FALSE ){
					$this->data[ $key ] = $decrypted;
				}
			}
		}
	}


	public function get( $name ){
		return $this->data[ $name ] ?? NULL;
	}


	public function is_encrypted( $key ){
		return in_array( $key, $this->encryptedElements );
	}


	private function get_sender_key( $forCrypto = FALSE ){
		if ( is_null( $this->senderPubKey ) ){
			if ( $forCrypto && $pubKey = $this->get('Public-Key') ){
				$this->senderPubKey = $pubKey;
			}
			else {
				$sender = $this->get('From');
				if ( $sender && is_callable( $this->keyRetrievalFunction ) ){
					$this->senderPubKey = call_user_func( $this->keyRetrievalFunction, $sender, $this );
				}
			}
		}
		if ( empty( $this->senderPubKey ) ){
			return FALSE;
		}
		return $this->senderPubKey;
	}


	public function get_signature_status( $useEmbeddedKey = FALSE ){
		if ( ! $signature = $this->get('Signature') ){
			$this->signatureStatus = -1;
			$this->signatureStatusMessage = 'Missing signature';
			return FALSE;
		}
		if ( $useEmbeddedKey ){
			if ( ! $key = $this->get('Public-Key') ){
				$this->signatureStatus = -3;
				$this->signatureStatusMessage = 'Missing public key';
				return FALSE;
			}
		}
		else {
			if ( ! $this->get('From') ){
				$this->signatureStatus = -5;
				$this->signatureStatusMessage = 'Missing sender';
				return FALSE;
			}
			$key = $this->get_sender_key();
			if ( ! $key ){
				$this->signatureStatus = -6;
				$this->signatureStatusMessage = 'Unknown sender';
				return FALSE;
			}
		}
		$unsignedMessage = substr( $this->rawMessage, strpos( $this->rawMessage, "\n" ) + 1 );
		$success = $this->crypto->verify_signature( $signature, $unsignedMessage, $key );
		if ( ! $success ){
			$this->signatureStatus = -9;
			$this->signatureStatusMessage = 'Verification failed (' . $this->crypto->lastError . ')';
			return FALSE;

		}
		$this->signatureStatus = 1;
		$this->signatureStatusMessage = 'Signature verified successfully';
		return TRUE;
	}

}

// end of file incoming_message.class.php