<?php

namespace LdapRecord;

use Closure;
use ErrorException;
use Exception;

trait HandlesConnection
{
    /**
     * The LDAP host that is currently connected.
     *
     * @var string|null
     */
    protected $host;

    /**
     * The LDAP connection resource.
     *
     * @var resource|null
     */
    protected $connection;

    /**
     * The bound status of the connection.
     *
     * @var bool
     */
    protected $bound = false;

    /**
     * Whether the connection must be bound over SSL.
     *
     * @var bool
     */
    protected $useSSL = false;

    /**
     * Whether the connection must be bound over TLS.
     *
     * @var bool
     */
    protected $useTLS = false;

    /**
     * @inheritdoc
     */
    public function isUsingSSL()
    {
        return $this->useSSL;
    }

    /**
     * @inheritdoc
     */
    public function isUsingTLS()
    {
        return $this->useTLS;
    }

    /**
     * @inheritdoc
     */
    public function isBound()
    {
        return $this->bound;
    }

    /**
     * @inheritdoc
     */
    public function isConnected()
    {
        return ! is_null($this->connection);
    }

    /**
     * @inheritdoc
     */
    public function canChangePasswords()
    {
        return $this->isUsingSSL() || $this->isUsingTLS();
    }

    /**
     * @inheritdoc
     */
    public function ssl($enabled = true)
    {
        $this->useSSL = $enabled;

        return $this;
    }

    /**
     * @inheritdoc
     */
    public function tls($enabled = true)
    {
        $this->useTLS = $enabled;

        return $this;
    }

    /**
     * @inheritdoc
     */
    public function setOptions(array $options = [])
    {
        foreach ($options as $option => $value) {
            $this->setOption($option, $value);
        }
    }

    /**
     * @inheritdoc
     */
    public function getHost()
    {
        return $this->host;
    }

    /**
     * @inheritdoc
     */
    public function getConnection()
    {
        return $this->connection;
    }

    /**
     * @inheritdoc
     */
    public function getProtocol()
    {
        return $this->isUsingSSL() ? LdapInterface::PROTOCOL_SSL : LdapInterface::PROTOCOL;
    }

    /**
     * @inheritdoc
     */
    public function getExtendedError()
    {
        return $this->getDiagnosticMessage();
    }

    /**
     * Convert warnings to exceptions for the given operation.
     *
     * @param Closure $operation
     *
     * @throws LdapRecordException
     *
     * @return mixed
     */
    protected function executeFailableOperation(Closure $operation)
    {
        // If some older versions of PHP, errors are reported instead of throwing
        // exceptions, which could be a signifcant detriment to our application.
        // Here, we will enforce these operations to throw exceptions instead.
        set_error_handler(function ($severity, $message, $file, $line) {
            if (! $this->shouldBypassError($message)) {
                throw new ErrorException($message, $severity, $severity, $file, $line);
            }
        });

        try {
            if (($result = $operation()) !== false) {
                return $result;
            }

            // If the failed query operation was a based on a query being executed
            // -- such as a search, read, or listing, then we can safely return
            // the failed response here and prevent throwning an exception.
            if ($this->shouldBypassFailure($method = debug_backtrace()[1]['function'])) {
                return $result;
            }

            throw new Exception("LDAP operation [$method] failed.");
        } catch (ErrorException $e) {
            throw LdapRecordException::withDetailedError($e, $this->getDetailedError());
        } finally {
            restore_error_handler();
        }
    }

    /**
     * Determine if the failed operation should be bypassed.
     *
     * @param string $method
     *
     * @return bool
     */
    protected function shouldBypassFailure($method)
    {
        return in_array($method, ['search', 'read', 'listing']);
    }

    /**
     * Determine if the error should be bypassed.
     *
     * @param string $error
     *
     * @return bool
     */
    protected function shouldBypassError($error)
    {
        return $this->causedByPaginationSupport($error) || $this->causedBySizeLimit($error) || $this->causedByNoSuchObject($error);
    }

    /**
     * Determine if the current PHP version supports server controls.
     *
     * @deprecated since v2.5.0
     *
     * @return bool
     */
    public function supportsServerControlsInMethods()
    {
        return version_compare(PHP_VERSION, '7.3.0') >= 0;
    }

    /**
     * Generates an LDAP connection string for each host given.
     *
     * @param string|array $hosts
     * @param string       $port
     *
     * @return string
     */
    protected function makeConnectionUris($hosts, $port)
    {
        // If an attempt to connect via SSL protocol is being performed,
        // and we are still using the default port, we will swap it
        // for the default SSL port, for developer convenience.
        if ($this->isUsingSSL() && $port == LdapInterface::PORT) {
            $port = LdapInterface::PORT_SSL;
        }

        // The blank space here is intentional. PHP's LDAP extension
        // requires additional hosts to be seperated by a blank
        // space, so that it can parse each individually.
        return implode(' ', $this->assembleHostUris($hosts, $port));
    }

    /**
     * Assemble the host URI strings.
     *
     * @param array|string $hosts
     * @param string       $port
     *
     * @return array
     */
    protected function assembleHostUris($hosts, $port)
    {
        return array_map(function ($host) use ($port) {
            return "{$this->getProtocol()}{$host}:{$port}";
        }, (array) $hosts);
    }
}
