<?php

class DOMTablet extends DOMTable {

	protected $widgets = array(
		"search" => null,
		"bulk" => null
	);
	
	protected $widget_div;
	protected $paginate_div;
	
	protected $primary_key = null;
	protected $bulk_data;
	
	protected $marker = 'paged';
	
	private $wrapper;
	
	public function __construct( ?string $tablename = null ) {
		
		libxml_use_internal_errors(true);
		
		parent::__construct( $tablename );
		
		// ---- [{ Add widgets container }] -----
		
		$this->widget_div = $this->doc->createElement('div');
		$this->widget_div->setAttribute('class', 'row row-cols-auto dt-widgets');
		$this->container->insertBefore( $this->widget_div, $this->container->firstChild );
		
		// ---- [{ Add pagination container }] -----
		
		$this->paginate_div = $this->doc->createElement('div');
		$this->paginate_div->setAttribute('class', 'mt-3 dt-paginate');
		$this->container->appendChild( $this->paginate_div );
		
		// ---- [{ Add container attribute }] ----
		
		$this->container->setAttribute( 'data-domtablet', $this->tablename );
		
		// ---- [{ Get current page }] ----
		
		$this->page( $_GET[ $this->marker ] ?? 1 );
		
	}
	
	public function wrap( string $class = '' ) {
		
		if( $this->wrapper ) return;
		
		$this->wrapper = $this->doc->createElement('div');
		$this->wrapper->setAttribute('class', $class);
		
		$card = $this->doc->createElement('div');
		$card->setAttribute('class', "card");
		
		$card_body = $this->doc->createElement('div');
		$card_body->setAttribute('class', 'card-body');
		
		$card->appendChild( $card_body );
		$this->wrapper->appendChild( $card );
		
		$this->container->insertBefore( $this->wrapper, $this->table->parentNode );
		$card_body->appendChild( $this->table->parentNode );
		
	}
	
	public function unwrap() {
		if( !$this->wrapper ) return;
		$this->container->insertBefore( $this->table->parentNode, $this->wrapper );
		$this->wrapper->parentNode->removeChild( $this->wrapper );
		$this->wrapper = null;
	}
	
	public function widget( string $name, $value, $aug = null ) {
		if( method_exists($this, $name) ) $this->{$name}( $value, $aug );
	}
	
	protected function search( ?bool $value ) {
		
		if( $value ) {
			
			$div = $this->doc->createElement('div');
			$div->setAttribute('class', 'col dt-uss-search');
			
			$search = $_GET['search'] ?? null;
			
			$this->widgets['search'] = $this->innerHTML( $div, "
				<form method='GET'>
					<div class='d-flex mb-2'>
						<div class='w-100 me-1'>
							<input type='text' name='search' class='form-control text-sm' placeholder='search' value='{$search}'>
						</div>
						<div class='col-'>
							<button class='btn btn-outline-info text-sm'>
								<i class='lni lni-search-alt'></i>
							</button>
						</div>
					</div>
				</form>
			" );
			
		} else $this->widgets['search'] = null;
		
	}
	
	protected function bulk( ?array $data, ?string $primary_key = null ) {
		
		if( empty($primary_key) || is_numeric($primary_key) ) $primary_key = null;
		
		if( empty($data) ) $this->widgets['bulk'] = null;
		
		else {
			
			$div = $this->doc->createElement('div');
			$div->setAttribute('class', 'col col-md-3 dt-uss-bulk');
			
			$nonce = uss::nonce( "domtablet-{$this->tablename}" );
			
			$this->widgets['bulk'] = $this->innerHTML( $div, "
				<form method='POST' id='dt-{$this->tablename}-bulk'>
					<input type='hidden' name='bulk_table' value='{$this->tablename}'>
					<input type='hidden' name='bulk_nonce' value='{$nonce}'>
					<div class='d-flex mb-2'>
						<div class='w-100 me-1'>
							<select name='bulk_action' class='form-control text-sm text-capitalize' required=''>
								<option value=''> Select One </option>
							</select>
						</div>
						<div class=''>
							<button class='btn btn-primary text-sm'>Apply</button>
						</div>
					</div>
				</form>
			" );
			
			$select = $div->getElementsByTagName('select')->item(0);
			
			foreach( $data as $key => $value ) {
				$option = $this->doc->createElement('option');
				$option->setAttribute('value', uss::htmlentities($key));
				$text = $this->doc->createTextNode( $value );
				$option->appendChild( $text );
				$select->appendChild( $option );
			};
			
			$this->primary_key = $primary_key;
			$this->bulk_data = $data;
			
		};
		
	}
	
	
	private function checked( ?array $data = null ) {
		
		$checked = $this->widgets['bulk'] && !empty($this->columns[0]) && !empty($this->primary_key);
		
		if( is_array( $data ) ) {
			$approved = array_key_exists( $this->primary_key, $data );
			$checked = $checked && $approved;
		}
		
		return $checked;
		
	}
	
	public function custom_widget( string $name, ?string $htmlcode, ?callable $func = null ) {
		if( array_key_exists($name, $this->widgets) ) {
			if( is_null($htmlcode) ) unset( $this->widgets[ $name ] );
			return;
		};
		$div = $this->doc->createElement('div');
		$div->setAttribute('class', "col dt-custom-{$name}");
		$this->innerHTML( $div, $htmlcode );
		$this->widgets[ $name ] = $div;
		if( $func ) $func( $div );
	}
	
	protected function modify_data( $data, $func ) {
		$new_data = parent::modify_data( $data, $func );
		if( $this->checked( $data ) ) {
			$primary_value = uss::htmlentities( $new_data[ $this->primary_key ] );
			$new_data[':checked'] = "
				<div class='form-check'>
					<input type='checkbox' name='bulk_values[]' form='dt-{$this->tablename}-bulk' data-check='{$this->tablename}' class='form-check-input' value='{$primary_value}' />
				</div>
			";
		}
		return $new_data;
	}
	
	public function prepare( ?callable $func = null, bool $print = false ) {
		
		// -- add checkbox to header; --
		
		if( $this->checked() ) {
			$this->columns[0] = array(
				':checked' => "<div class='form-check'>
					<input type='checkbox' class='form-check-input' data-check-all='{$this->tablename}'/>
				</div>"
			) + $this->columns[0];
		};
		
		parent::prepare( $func, false );
		
		foreach( $this->widgets as $div ) {
			if( $div ) $this->widget_div->appendChild( $div );
		};
		
		$this->createNav( $this->pagination(1) );
		
		$table = $this->doc->saveHTML( $this->container );
		return print_r( $table, !$print );
		
	}
	
	protected function pagination( int $siders ) {
		if( !$this->pages ) return [];
		$midpoint = $siders + 1;
		$limit = $midpoint + $siders;
		if( $this->page < $midpoint ) {
			$last = ( $this->pages > $limit ) ? $limit : $this->pages;
			$range = range(1, $last);
		} else if( $this->page > ($this->pages - $siders) ) {
			$first = ( $this->pages - $limit + 1 );
			if( $first < 1 ) $first = 1;
			$range = range( $first, $this->pages );
		} else {
			$range = range( $this->page - $siders, $this->page + $siders );
		};
		return array_combine($range, $range);
	}
	
	protected function createNav( array $range ) {
		
		if( count($range) < 2 ) return;
		
		$list = [];
		
		if( !in_array(1, array_keys($range)) ) {
			$range = array( 1 => "<i class='mdi mdi-chevron-double-left'></i>" ) + $range;
		};
		
		if( !in_array($this->pages, array_keys($range)) ) {
			$range[ $this->pages ] = "<i class='mdi mdi-chevron-double-right'></i>";
		}
		
		foreach( $range as $index => $text ) {
			$active = ( $index == $this->page ) ? 'active' : null;
			$list[] = "
				<li class='page-item {$active}'>
					<button class='page-link' name='{$this->marker}' type='submit' value='{$index}'>{$text}</button>
				</li>
			";
		};
		
		$buttons = implode('', $list);
		
		$data = $_GET;
		unset($data['query']);
		
		if( isset($data[ $this->marker ]) ) unset($data[ $this->marker ]);
		
		$queries = '';
		foreach( $data as $key => $value ) {
			$key = urlencode($key);
			$value = urlencode($value);
			$queries .= "<input type='hidden' name='{$key}' value='{$value}' />";
		}
		
		$this->innerHTML( $this->paginate_div, "
			<form method='GET'>
				{$queries}
				<ul class='pagination'>
					{$buttons}
				</ul>
			</form>
		");
		
	}

}
