<?php

namespace LowEntryUE4PHP\Classes\Internal\Rsa;

use LowEntryUE4PHP\LowEntry;


class RsaBigIntegerHelper
{
	private static $ZERO = null;
	private static $ONE = null;
	
	
	/**
	 * @return RsaBigInteger
	 */
	public static function ZERO()
	{
		$result = self::$ZERO;
		if($result === null)
		{
			$result = new RsaBigInteger(0);
			self::$ZERO = $result;
		}
		return $result;
	}
	
	/**
	 * @return RsaBigInteger
	 */
	public static function ONE()
	{
		$result = self::$ONE;
		if($result === null)
		{
			$result = new RsaBigInteger(1);
			self::$ONE = $result;
		}
		return $result;
	}
	
	
	/**
	 * @param RsaBigInteger $a
	 * @param RsaBigInteger $b
	 *
	 * @return RsaBigInteger
	 */
	public static function remainder($a, $b)
	{
		return $a->divide($b)[1];
	}
	
	/**
	 * @param int $bitLength
	 *
	 * @return RsaBigInteger|null
	 */
	public static function probablePrime($bitLength)
	{
		if($bitLength < 2)
		{
			//throw new ArithmeticException("$bitLength < 2");
			return null;
		}
		
		$bytes = $bitLength >> 3;
		$min = \str_repeat(chr(0), $bytes);
		$max = \str_repeat(chr(0xFF), $bytes);
		$msb = $bitLength & 7;
		if($msb)
		{
			$min = \chr(1 << ($msb - 1)) . $min;
			$max = \chr((1 << $msb) - 1) . $max;
		}
		else
		{
			$min[0] = \chr(0x80);
		}
		$min = new RsaBigInteger($min, 256);
		$max = new RsaBigInteger($max, 256);
		
		$result = (new RsaBigInteger())->randomPrime($min, $max);
		if(!$result)
		{
			return null;
		}
		return $result;
	}
	
	/**
	 * @param RsaBigInteger $a
	 * @param RsaBigInteger $b
	 *
	 * @return int
	 */
	public static function compareTo($a, $b)
	{
		return $a->compare($b);
	}
	
	/**
	 * @param RsaBigInteger $a
	 *
	 * @return int
	 */
	public static function bitLength($a)
	{
		return \strlen($a->toBytes()) * 8;
	}
	
	/**
	 * @param int[] $bytes Byte array
	 *
	 * @return RsaBigInteger
	 */
	public static function fromByteArray($bytes)
	{
		return new RsaBigInteger(LowEntry::bytesToHex($bytes), 16);
	}
	
	/**
	 * @param RsaBigInteger $a
	 *
	 * @return int[] Byte array
	 */
	public static function toByteArray($a)
	{
		return LowEntry::hexToBytes($a->toHex(true));
	}
}
