<?php

declare(strict_types=1);

namespace Crossroads\Magento\Test\Integration;

use Mage;
use Exception;
use Zend_Controller_Response_Http;
use Varien_Object;

class Response extends Zend_Controller_Response_Http {
    /**
     * Transport object for observers to perform
     *
     * @var Varien_Object
     */
    protected static $_transportObject = null;

    public function sendResponse()
    {
        Mage::dispatchEvent('http_response_send_before', array('response'=>$this));
        return parent::sendResponse();
    }

    /**
     * Additionally check for session messages in several domains case
     *
     * @param string $url
     * @param int $code
     * @return Mage_Core_Controller_Response_Http
     */
    public function setRedirect($url, $code = 302)
    {
        /**
         * Use single transport object instance
         */
        if (self::$_transportObject === null) {
            self::$_transportObject = new Varien_Object;
        }
        self::$_transportObject->setUrl($url);
        self::$_transportObject->setCode($code);
        Mage::dispatchEvent('controller_response_redirect',
                array('response' => $this, 'transport' => self::$_transportObject));

        return parent::setRedirect(self::$_transportObject->getUrl(), self::$_transportObject->getCode());
    }

    /**
     * Method send already collected headers and exit from script
     */
    public function sendHeadersAndExit()
    {
        throw new Exception("Attempting to send headers and exit");
    }

    protected $hasSentOutput = false;

    public function sendHeaders() {
        // Empty
    }

    public function canSendHeaders($throw = false) {
        if($this->hasSentOutput && $throw) {
            throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent');
        }

        return !$this->hasSentOutput;
    }

    public function outputBody() {
        $this->hasSentOutput = true;
    }

    public function getBody($spec = false) {
        return implode('', $this->_body);
    }

    public function hasSentOutput() {
        return $this->hasSentOutput;
    }

    public function setHeader($name, $value, $replace = false)
    {
        $name = $this->_normalizeHeader($name);
        $value = (string) $value;

        if ($replace) {
            foreach ($this->_headers as $key => $header) {
                if ($name == $header['name']) {
                    unset($this->_headers[$key]);
                }
            }
        }

        // Magento rarely uses setHttpResponseCode, use it here to make sure it
        // is testable
        if(in_array($name, ["Http/1.1", "Status"])) {
            $this->setHttpResponseCode((int)$value);
        }

        $this->_headers[] = array(
            'name'    => $name,
            'value'   => $value,
            'replace' => $replace
        );

        return $this;
    }

    public function getHeader($key) {
        $name = $this->_normalizeHeader($key);
        $ret  = [];

        foreach($this->_headers as $key => $header) {
            if($name == $header["name"]) {
                $ret[] = $header["value"];
            }
        }

        return count($ret) > 1 ? $ret : $ret[0] ?? null;
    }

    public function getHeadersAsText() {
        $headers = $this->_headersRaw;

        array_unshift($headers, 'HTTP/1.1 ' . $this->_httpResponseCode);

        foreach ($this->_headers as $header) {
            $headers[] = $header['name'] . ': ' . $header['value']; // , $header['replace']);
        }

        return implode("\n", $headers);
    }

    public function __toString()
    {
        $parts = [$this->getHeadersAsText(), ""];

        if ($this->isException()) {
            foreach ($this->getException() as $e) {
                $parts[] = $e->__toString();
            }
        }
        else {
            $parts[] = $this->getBody();
        }

        return implode("\n", $parts);
    }
}
