<?php
 namespace MongoDB;
 use MongoDB\Driver\ClientEncryption;
 use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException;
 use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
 use MongoDB\Driver\Manager;
 use MongoDB\Driver\ReadConcern;
 use MongoDB\Driver\ReadPreference;
 use MongoDB\Driver\Session;
 use MongoDB\Driver\WriteConcern;
 use MongoDB\Exception\InvalidArgumentException;
 use MongoDB\Exception\UnexpectedValueException;
 use MongoDB\Exception\UnsupportedException;
 use MongoDB\Model\BSONArray;
 use MongoDB\Model\BSONDocument;
 use MongoDB\Model\DatabaseInfoIterator;
 use MongoDB\Operation\DropDatabase;
 use MongoDB\Operation\ListDatabases;
 use MongoDB\Operation\Watch;
 use function is_array;
 class Client {
 private static $defaultTypeMap = [ 'array' => BSONArray::class, 'document' => BSONDocument::class, 'root' => BSONDocument::class, ];
 private static $wireVersionForReadConcern = 4;
 private static $wireVersionForWritableCommandWriteConcern = 5;
 private $manager;
 private $readConcern;
 private $readPreference;
 private $uri;
 private $typeMap;
 private $writeConcern;
 public function __construct($uri = 'mongodb://127.0.0.1/', array $uriOptions = [], array $driverOptions = []) {
 $driverOptions += ['typeMap' => self::$defaultTypeMap];
 if (! is_array($driverOptions['typeMap'])) {
 throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array');
 }
 if (isset($driverOptions['autoEncryption']['keyVaultClient'])) {
 if ($driverOptions['autoEncryption']['keyVaultClient'] instanceof self) {
 $driverOptions['autoEncryption']['keyVaultClient'] = $driverOptions['autoEncryption']['keyVaultClient']->manager;
 }
 elseif (! $driverOptions['autoEncryption']['keyVaultClient'] instanceof Manager) {
 throw InvalidArgumentException::invalidType('"keyVaultClient" autoEncryption option', $driverOptions['autoEncryption']['keyVaultClient'], [self::class, Manager::class]);
 }
 }
 $this->uri = (string) $uri;
 $this->typeMap = isset($driverOptions['typeMap']) ? $driverOptions['typeMap'] : null;
 unset($driverOptions['typeMap']);
 $this->manager = new Manager($uri, $uriOptions, $driverOptions);
 $this->readConcern = $this->manager->getReadConcern();
 $this->readPreference = $this->manager->getReadPreference();
 $this->writeConcern = $this->manager->getWriteConcern();
 }
 public function __debugInfo() {
 return [ 'manager' => $this->manager, 'uri' => $this->uri, 'typeMap' => $this->typeMap, 'writeConcern' => $this->writeConcern, ];
 }
 public function __get($databaseName) {
 return $this->selectDatabase($databaseName);
 }
 public function __toString() {
 return $this->uri;
 }
 public function createClientEncryption(array $options) {
 if (isset($options['keyVaultClient'])) {
 if ($options['keyVaultClient'] instanceof self) {
 $options['keyVaultClient'] = $options['keyVaultClient']->manager;
 }
 elseif (! $options['keyVaultClient'] instanceof Manager) {
 throw InvalidArgumentException::invalidType('"keyVaultClient" option', $options['keyVaultClient'], [self::class, Manager::class]);
 }
 }
 return $this->manager->createClientEncryption($options);
 }
 public function dropDatabase($databaseName, array $options = []) {
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
 $options['writeConcern'] = $this->writeConcern;
 }
 $operation = new DropDatabase($databaseName, $options);
 return $operation->execute($server);
 }
 public function getManager() {
 return $this->manager;
 }
 public function getReadConcern() {
 return $this->readConcern;
 }
 public function getReadPreference() {
 return $this->readPreference;
 }
 public function getTypeMap() {
 return $this->typeMap;
 }
 public function getWriteConcern() {
 return $this->writeConcern;
 }
 public function listDatabases(array $options = []) {
 $operation = new ListDatabases($options);
 $server = select_server($this->manager, $options);
 return $operation->execute($server);
 }
 public function selectCollection($databaseName, $collectionName, array $options = []) {
 $options += ['typeMap' => $this->typeMap];
 return new Collection($this->manager, $databaseName, $collectionName, $options);
 }
 public function selectDatabase($databaseName, array $options = []) {
 $options += ['typeMap' => $this->typeMap];
 return new Database($this->manager, $databaseName, $options);
 }
 public function startSession(array $options = []) {
 return $this->manager->startSession($options);
 }
 public function watch(array $pipeline = [], array $options = []) {
 if (! isset($options['readPreference']) && ! is_in_transaction($options)) {
 $options['readPreference'] = $this->readPreference;
 }
 $server = select_server($this->manager, $options);
 if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
 $options['readConcern'] = $this->readConcern;
 }
 if (! isset($options['typeMap'])) {
 $options['typeMap'] = $this->typeMap;
 }
 $operation = new Watch($this->manager, null, null, $pipeline, $options);
 return $operation->execute($server);
 }
 }
 