<?php

namespace Illuminate\Database\Capsule;

use PDO;
use Illuminate\Container\Container;
use Illuminate\Database\DatabaseManager;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Support\Traits\CapsuleManagerTrait;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Database\Connectors\ConnectionFactory;
// get this namespace
class Manager
{//get the Capsule like the
   // capsule manager
    use CapsuleManagerTrait;// use the Capsule Manager Trait

    /**
     * The database manager instance.
     *
     * @var \Illuminate\Database\DatabaseManager
     */
    protected $manager;//The database manager instance.

    /**
     * Create a new database capsule manager.
     *
     * @param  \Illuminate\Container\Container|null  $container
     * @return void
     */
    public function __construct(Container $container = null)
    {//Create a new database capsule manager.
        $this->setupContainer($container ?: new Container);// setup Container
       // container get the container

        // Once we have the container setup, we will setup the default configuration
        // options in the container "config" binding. This will make the database
        // manager behave correctly since all the correct binding are in place.
        $this->setupDefaultConfiguration();
       // Once we have the container setup, we will setup the default configuration
       // options in the container "config" binding. This will make the database
       // manager behave correctly since all the correct binding are in place.
       // setup Default Configuration

        $this->setupManager();//setup Manager
    }

    /**
     * Setup the default database configuration options.
     *
     * @return void
     */
    protected function setupDefaultConfiguration()
    {//Setup the default database configuration options.
        $this->container['config']['database.fetch'] = PDO::FETCH_OBJ;
       // PDO::FETCH_OBJ  this container
       // set the config

        $this->container['config']['database.default'] = 'default';
       // default the config
    }

    /**
     * Build the database manager instance.
     *
     * @return void
     */
    protected function setupManager()
    {//Build the database manager instance.
        $factory = new ConnectionFactory($this->container);// factory get the Connection Factory

        $this->manager = new DatabaseManager($this->container, $factory);
       //Database Manager
       // set the manager
    }

    /**
     * Get a connection instance from the global manager.
     *
     * @param  string  $connection
     * @return \Illuminate\Database\Connection
     */
    public static function connection($connection = null)
    {//Get a connection instance from the global manager.
        return static::$instance->getConnection($connection);
    }// return static::$instance->getConnection($connection);
   // return the getConnection

    /**
     * Get a fluent query builder instance.
     *
     * @param  string  $table
     * @param  string  $connection
     * @return \Illuminate\Database\Query\Builder
     */
    public static function table($table, $connection = null)
    {//Get a fluent query builder instance.
        return static::$instance->connection($connection)->table($table);
    }//instance connection table

    /**
     * Get a schema builder instance.
     *
     * @param  string  $connection
     * @return \Illuminate\Database\Schema\Builder
     */
    public static function schema($connection = null)
    {//Get a schema builder instance.
        return static::$instance->connection($connection)->getSchemaBuilder();
    }// table and the get SchemaBuilder

    /**
     * Get a registered connection instance.
     *
     * @param  string  $name
     * @return \Illuminate\Database\Connection
     */
    public function getConnection($name = null)
    {
        return $this->manager->connection($name);//connection
    }//Get a registered connection instance.

    /**
     * Register a connection with the manager.
     *
     * @param  array   $config
     * @param  string  $name
     * @return void
     */
    public function addConnection(array $config, $name = 'default')
    {//Register a connection with the manager.
       //addConnection
        $connections = $this->container['config']['database.connections'];//get the connections

        $connections[$name] = $config;//config this connections

        $this->container['config']['database.connections'] = $connections;// set the config
    }

    /**
     * Bootstrap Eloquent so it is ready for usage.
     *
     * @return void
     */
    public function bootEloquent()
    {//Bootstrap Eloquent so it is ready for usage.
        Eloquent::setConnectionResolver($this->manager);//Eloquent::setConnectionResolver(this->mamager)

        // If we have an event dispatcher instance, we will go ahead and register it
        // with the Eloquent ORM, allowing for model callbacks while creating and
        // updating "model" instances; however, if it not necessary to operate.
        if ($dispatcher = $this->getEventDispatcher()) {
            Eloquent::setEventDispatcher($dispatcher);
        }
       // If we have an event dispatcher instance, we will go ahead and register it
       // with the Eloquent ORM,allowing for model callbacks while creating and
       // updating "model" instance; however,if it not necessary to operate.s
    }

    /**
     * Set the fetch mode for the database connections.
     *
     * @param  int  $fetchMode
     * @return $this
     */
    public function setFetchMode($fetchMode)
    {
        $this->container['config']['database.fetch'] = $fetchMode;//set config

        return $this;//return the this
    }//Set the fetch mode for the database connections

    /**
     * Get the database manager instance.
     *
     * @return \Illuminate\Database\DatabaseManager
     */
    public function getDatabaseManager()
    {
        return $this->manager;// set the manager
    }//Get the database manager instance.

    /**
     * Get the current event dispatcher instance.
     *
     * @return \Illuminate\Contracts\Events\Dispatcher|null
     */
    public function getEventDispatcher()
    {
        if ($this->container->bound('events')) {
            return $this->container['events'];//return container
        }//getEventDispatcher
    }//Get the current event dispatcher instance.

    /**
     * Set the event dispatcher instance to be used by connections.
     *
     * @param  \Illuminate\Contracts\Events\Dispatcher  $dispatcher
     * @return void
     */
    public function setEventDispatcher(Dispatcher $dispatcher)
    {
        $this->container->instance('events', $dispatcher);// the instance
    }//Set the event dispatcher instance to be used by connections

    /**
     * Dynamically pass methods to the default connection.
     *
     * @param  string  $method
     * @param  array   $parameters
     * @return mixed
     */
    public static function __callStatic($method, $parameters)
    {// callStatic
       // call_user_func_array
        return call_user_func_array([static::connection(), $method], $parameters);
    }//Dynamically pass methods to the default connection.
}