<?php
	namespace Juju\Http;
	require_once(realpath(dirname(__DIR__).'/events.trait.php'));
	require_once(realpath(dirname(__DIR__).'/App/router.class.php'));
	use \Juju\{App\Router, Events};

	class Response {
		use Events;
		public $output = '';
		public $body = '';
		private $code = 200;
		public $headers = [];
		protected $open = true;
		public function __construct(){}
		public function __toString(){
			return $this->body;
		}
		public function clear(){
			if($this->open){
				$this->fire('clear');
				$this->body = '';
			}
			return $this;
		}
		public function clear_headers(){
			if($this->open){
				$this->fire('clear_headers');
				$this->headers = [];
			}
			return $this;
		}
		public function clear_header(string $name){
			foreach($this->headers as $key => $header){
				if($header[0] == $name){
					$this->fire('clear_header', $name);
					array_splice($this->headers, $key, 1);
				}
			}
			return $this;
		}
		public function write(string $chunk){
			$this->fire('write', $chunk);
			if($this->open){
				$this->body .= $chunk;
			}
			return $this;
		}
		public function json($json){
			if(is_array($json)){
				array_walk_recursive($json, function(&$item, $key){
					if(!mb_detect_encoding($item, 'utf-8', true)){
						$item = utf8_encode($item);
					}
				});
			}
			$this->fire('json', $json);
			$this->write(json_encode($json));
			if(json_last_error() != JSON_ERROR_NONE){
				throw new \Exception(json_last_error_msg());
			}
			return $this;
		}
		public function header(string $name, string $value){
			if($this->open){
				$this->fire('header', $name, $value);
				array_push(
					$this->headers,
					[
						$name,
						$value
					]
				);
			}
			return $this;
		}
		public function redirect(string $url){
			$this->fire('redirect', $url);
			$this->header('Location', Router::url($url));
			return $this;
		}
		public function end(string $chunk=''){
			if($this->open){
				$this->write($chunk);
				$this->fire('end');
				$this->open = false;
			}
			return $this;
		}
		public function img(Image $img, string $type = null){
			if(!$type){
				$type = $img->type;
			}
			$this->fire('image', $img, $type);
			$this->clear_header('Content-Type')
				->header('Content-Type', 'image/'.$type);
			if(!is_a($img, 'Image')){
				$img = new Image(100, 20);
				$img->text('Invalid Image',0,0,'black',12);
			}
			ob_start();
			$img();
			$this->write(ob_get_contents());
			ob_end_clean();
			return $this;
		}
		public function code(int $code=null){
			if(is_null($code)){
				return $this->code;
			}
			$this->fire('code', $code);
			$this->code = $code;
			return $this;
		}
		public function shutdown(){
			$this->fire('beforeshutdown');
			if($this->open){
				$this->end();
			}
			$this->fire('shutdown');
			http_response_code($this->code);
			foreach($this->headers as $k => $header){
				header("{$header[0]}: $header[1]");
			}
			echo $this->body;
			flush();
			$this->fire('aftershutdown');
		}
	}
?>