<?php
namespace SabaiApps\Framework\Application;

/**
 * Abstract class for HTTP responses.
 * Provides methods for setting headers, sending status codes, and handling different response types.
 */
abstract class AbstractHttpResponse extends AbstractResponse {

	/**
	 * HTTP status codes and their standard messages.
	 *
	 * @var array
	 */
	private static $_codes = array(
		100 => 'Continue',
		101 => 'Switching Protocols',
		200 => 'OK',
		201 => 'Created',
		202 => 'Accepted',
		203 => 'Non-Authoritative Information',
		204 => 'No Content',
		205 => 'Reset Content',
		206 => 'Partial Content',
		300 => 'Multiple Choices',
		301 => 'Moved Permanently',
		302 => 'Found',
		303 => 'See Other',
		304 => 'Not Modified',
		305 => 'Use Proxy',
		306 => '(Unused)',
		307 => 'Temporary Redirect',
		400 => 'Bad Request',
		401 => 'Unauthorized',
		402 => 'Payment Required',
		403 => 'Forbidden',
		404 => 'Not Found',
		405 => 'Method Not Allowed',
		406 => 'Not Acceptable',
		407 => 'Proxy Authentication Required',
		408 => 'Request Timeout',
		409 => 'Conflict',
		410 => 'Gone',
		411 => 'Length Required',
		412 => 'Precondition Failed',
		413 => 'Request Entity Too Large',
		414 => 'Request-URI Too Long',
		415 => 'Unsupported Media Type',
		416 => 'Requested Range Not Satisfiable',
		417 => 'Expectation Failed',
		422 => 'Unprocessable Entity',
		500 => 'Internal Server Error',
		501 => 'Not Implemented',
		502 => 'Bad Gateway',
		503 => 'Service Unavailable',
		504 => 'Gateway Timeout',
		505 => 'HTTP Version Not Supported',
	);

	/**
	 * Array of HTTP headers to send.
	 *
	 * @var array
	 */
	protected $_headers = array();

	/**
	 * Sets a header to be sent with the response.
	 *
	 * @param string $name Header name.
	 * @param string $value Header value.
	 * @return $this
	 */
	public function setHeader( $name, $value ) {
		$this->_headers[ $name ] = $value;

		return $this;
	}

	/**
	 * Checks if a header is set.
	 *
	 * @param string $name Header name.
	 * @return bool
	 */
	public function hasHeader( $name ) {
		return isset( $this->_headers[ $name ] );
	}

	/**
	 * Sends the response based on the context status.
	 *
	 * @param Context $context
	 * @return mixed
	 */
	public function send( Context $context ) {
		switch ( $context->getStatus() ) {
			case Context::STATUS_SUCCESS:
				return $this->_sendSuccess( $context );
			case Context::STATUS_ERROR:
				return $this->_sendError( $context );
			case HttpContext::STATUS_REDIRECT:
				return $this->_sendRedirect( $context );
			default:
				return $this->_sendView( $context );
		}
	}

	/**
	 * Sends a redirect header.
	 *
	 * @param HttpContext $context
	 */
	protected function _sendRedirect( HttpContext $context ) {
		self::sendHeader( 'Location', $context->getRedirectUrl() );
	}

	/**
	 * Sends all headers set for the response.
	 */
	protected function _sendHeaders() {
		foreach ( $this->_headers as $name => $value ) {
			self::sendHeader( $name, $value );
		}
	}

	/**
	 * Sends a single header.
	 *
	 * @param string $name Header name.
	 * @param string $value Header value.
	 */
	public static function sendHeader( $name, $value ) {
		header( str_replace( array( "\r", "\n" ), '', $name . ': ' . $value ) );
	}

	/**
	 * Sends an HTTP status header.
	 *
	 * @param int         $code HTTP status code.
	 * @param string|null $message Optional custom status message.
	 */
	public static function sendStatusHeader( $code, $message = null ) {
		if ( headers_sent() ) {
			return;
		}

		if ( ! isset( self::$_codes[ $code ] ) ) {
			// Custom status code requires status message
			if ( ! isset( $message ) ) {
				return;
			}
		} else {
			$message = self::$_codes[ $code ];
		}
		$protocol = isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';
		header( sprintf( '%s %d %s', $protocol, $code, $message ), true, $code );
	}

	public static function sendNoCacheHeaders() {
		self::sendHeader( 'Cache-Control', 'no-cache, no-store, must-revalidate' );
		self::sendHeader( 'Pragma', 'no-cache' );
		self::sendHeader( 'Expires', '0' );
	}
}
