<?php

namespace WPD\Security;

use WPD\Application\Config;

final class TransportPolicy
{
    const HTTPS = 'https';
    const HTTP_EMERGENCY = 'http-emergency';
    const BLOCKED_HTTP = 'blocked-http';

    private $config;
    private $server;

    public function __construct(Config $config, array $server)
    {
        $this->config = $config;
        $this->server = $server;
    }

    public function mode()
    {
        if ($this->isHttps()) {
            return self::HTTPS;
        }
        if ($this->config->get('allow_insecure_http', false) && $this->hasAllowedIps()) {
            return self::HTTP_EMERGENCY;
        }
        return self::BLOCKED_HTTP;
    }

    public function isHttps()
    {
        if (!empty($this->server['HTTPS']) && strtolower((string) $this->server['HTTPS']) !== 'off') {
            return true;
        }
        if (isset($this->server['SERVER_PORT']) && (int) $this->server['SERVER_PORT'] === 443) {
            return true;
        }
        $remote = $this->clientAddress();
        $trusted = $this->config->get('trusted_proxy_ips', array());
        if (in_array($remote, $trusted, true)) {
            $forwarded = isset($this->server['HTTP_X_FORWARDED_PROTO']) ? strtolower(trim((string) $this->server['HTTP_X_FORWARDED_PROTO'])) : '';
            return $forwarded === 'https';
        }
        return false;
    }

    public function clientAllowed()
    {
        $allowed = $this->config->get('allowed_ips', array());
        return !$allowed || in_array($this->clientAddress(), $allowed, true);
    }

    public function clientAddress()
    {
        return isset($this->server['REMOTE_ADDR']) ? (string) $this->server['REMOTE_ADDR'] : '';
    }

    private function hasAllowedIps()
    {
        return count($this->config->get('allowed_ips', array())) > 0;
    }
}
