<?

class data_query {

	private $rows;

	public function __construct($rows) {
		$this->rows = $rows;
	}

	public function where($callback) {
		$result = [];
		foreach($this->rows as $key => $row) {
			if($callback($row, $key)) {
				$result[] = $row;
			}
		}
		return $result;
	}

	public function first() {
		if($this->rows->length > 0) {
			return $this->rows[0];
		}
		return NULL;
	}

	public function last() {
		if($this->rows->length > 0) {
			return $this->rows[$this->rows->length-1];
		}
		return NULL;
	}	
}

class table_structure_update {
	public function __construct($init_command, $data_instance) {
		$create_commands = $object->strings->split($init_command, 'CREATE TABLE IF NOT EXISTS');
		foreach($create_commands as $item) {
			$table_parts = $object->strings->split($item, '(');
			if($table_parts->length > 1) {
				$nametrimmed = $object->strings->trim($table_parts[0]);
				$sub_items = $object->strings->split($table_parts[1], ')')[0];
				$sub_items = $object->strings->split($sub_items, ',');
				$index = 0;
				$columns = $data_instance->table_columns($nametrimmed);
				foreach($sub_items as $sub_item) {
					$sub_item_value = $object->strings->split($object->strings->trim($sub_item), ' ')[0];
					$flag = false;
					foreach($columns as $column) {
						if($column == $sub_item_value) {
							$flag = true;
						}
					}
					if(!$flag) {
						$data_instance->execute('ALTER TABLE '.$nametrimmed.' ADD COLUMN '.$sub_item, []);
					} else {
					}
				}
			}
		}
	}
}

class statement {
	public function generate($x, $table, $set_type=(-1)) {
		$output = NULL;
		$keys = [];
		$type = 0;
		if($x->length > 0) {
			if($object->isset($x['id'])) {
				if($x['id'] == '-1') {
					$type = 1;	
				} else {
					$type = 0;	
				}
			} else {
				$type = 1;	
			}
			if($set_type != (-1)) {
				$type = $set_type;
			}
			if($type == 0) {
				$output = 'UPDATE '.$table.' SET ';
				if($object->isset($x['id'])) {
					$counter = 0;
					foreach($x as $key => $x_value) {
						$keys[] = $key;
						if($key != 'id') {
							if($counter > 0) {
								$output = $output.', ';
							}
							$output = $output.$key.' = ?';
							$counter = $counter+1;
						}
					}
					$output = $output.' WHERE id = ?';
				}
			} else {
				$output = 'INSERT INTO '.$table.' (';
				$counter = 0;
				foreach($x as $key => $x_value) {
					$keys[] = $key;
					if($counter > 0) {
						$output = $output.', ';
					}
					$output = $output.$key;
					$counter = $counter+1;
				}
				$counter = 0;
				$output = $output.') VALUES (';
				foreach($x as $key => $x_value) {
					if($counter > 0) {
						$output = $output.', ';
					}
					$output = $output.'? ';
					$counter = $counter+1;
				}
				$output = $output.')';
			}
			return $output;
		}
		return NULL;
	}
}

class extension {

	protected $data;
	protected $base;
	protected $statement;

	public function __construct($base) {
		$this->base = $base;

		$this->init();
	}

	public function base_init($init_string=NULL) {
		$self_sql = $this->data;
		/*$this->data->last_id = function($v) {
			if($object->isset($v['id'])) {
				return $v['id'];
			}
			return $self_sql->last_insert_id();
		};

		if($init_string != NULL) {
			$init_tables = $object->strings->split($init_string, ';');
			foreach($init_tables as $init_table) {
				$this->data->execute($init_table, []);
			}
			$table_update = new table_structure_update($init_string, $this->data);
		}*/
	}
}

class base {
	
	public $apps=NULL;
	
	private $dict = NULL;

	public $indexing_in_progress = false;

	public function __construct() {
		$data->main_instance = $data->fetch('player');
		$data->statement = new statement();
		$object->deep_copy = function($input) {
			return $object->fromJSON($object->toJSON($input));
		};
		$object->index_of = function($input, $search_value) {
			foreach($input as $indexofkey => $value) {
				if($search_value == $value) {
					return $indexofkey;
				}
			}
			return -1;
		};
		$object->union = function($a, $b, $comparator) {
			foreach($b as $b_value) {
				$exists = false;
				foreach($a as $a_value) {
					$comparator_result = $comparator($a_value, $b_value);
					if($comparator_result) {
						$exists = true;
					}
				}
				if(!$exists) {
					$a[] = $b_value;
				}
			}
			return NULL;
		};
		$object->map = function($arr, $func) {
			$result = [];
			foreach($arr as $row) {
				$result[] = $func($row);
			}
			return $result;
		};

		/*$object->create = function() {
			$test = ['test' => 'test'];
			delete $test['test'];
			return $test;
		};*/

		$object->concat = function($a, $b) {
			$result = [...$a];
			foreach($b as $b_value) {
				$result[] = $b_value;
			}
			return $result;
		};

		$object->get_first_row = function($rows) {
			if($rows->length > 0) {
				return $rows[0];
			}
			return NULL;
		};

    	$files->append_path_depr = function($path, $file) {
    		$path_strlen = $object->strings->strlen($path);
    		$strrev = $object->strings->strrev($path);
    		if($object->strings->strpos($strrev, '/') == 0) {
    			$path = $object->strings->substr($path, 0, $path_strlen-1);
    		}
    		if($object->strings->strpos($file, '/') != 0) {
    			$file = '/'.$file;
    		}
    		return $path.$file;
    	};



		$object->count = function($arr) {
			return $arr->length;
		};

		$object->get_first_row = function($rows) {
			if($rows->length > 0) {
				return $rows[0];
			}
			return NULL;
		};

		$object->array_keys = function($value) {
			return $object->keys($value);
		};

    	$object->strings->explode = function($delimiter, $value) {
    		return $object->strings->split($value, $delimiter);
    	};

    	$object->strings->implode = function($delimiter, $values) {
    		return $object->strings->join($values, $delimiter);
    	};

    	$object->regex->preg_split = function($regex_value, $text, $mark_delimiters) {
			$preg_split_instance = new preg_split($regex_value, $text, $mark_delimiters);
			return $preg_split_instance->get();
		};

		$object->regex->preg_replace = function($regex_value, $replace_value, $text) {
			$split = $object->regex->preg_split($regex_value, $text, true);
			return $object->strings->join($split, $replace_value);
		};

    	$this->callbacks = [];

    	$self = $this;

    	$this->indexing_dictionary = [
    		'cinema' => false,
    		'tv' => false
    	];

		$this->apps = [
			'cinema' => new cinema_app($self),
    		'player' => new player_app($self),
    		'tv' => new tv_app($self)
    	];

		$this->run_main();
	}

	public function run_main() {

		$source = $files->read_text('streamline2/main', 'html');


		$html_parser_instance = new html_parser($source);
		$res = $html_parser_instance->parse();



		$object->preview_container = $res->get_window()->get_document()->query_selector('.preview_container')[0];
		$object->main_preview_video = $res->get_window()->get_document()->query_selector('video.preview_main')[0];
		$object->main_preview_web = $res->get_window()->get_document()->query_selector('web.mainweb')[0];
		
		$object->main_preview_video->get_media_tab()->register_callback(function() {
			$object->log('register 1');
		});

		$object->main_preview_video->get_media_tab()->register_callback(function() {
			$object->log('register 2');
		});

		$object->main_preview_video->get_media_tab()->register_callback(function($par) {
			$object->log('register 3');
		});

		$object->main_preview_video->get_media_tab()->register_callback(function($par) {
			$object->log('register 4');
		});

		$self = $this;

		$object->main_preview_web->get_webview()->init_messages(function($message_value) {
			if($message_value['action'] == 'respond') {
				$object->send('app.previews.play(data)', ['data' => NULL]);
				$self->hide_preview();
			}
		});

		$this->hide_preview();

		/*$box_values = [
			'display' => 0
		];

		$object->preview_container->get_layout()->set_box($box_values);*/
		/*$object->main_preview_video->get_media_tab()->play('/Volumes/TV/TV/Roseanne Season 1 - 10 - fiveofseven/Roseanne Season 01 - fiveofseven/Roseanne S01E01 Life and Stuff - fiveofseven.mp4');*/
	}

	public function display_preview($coordinates, $path, $title=NULL) {
		$object->main_preview_video->get_media_tab()->play($path);
		$object->main_preview_video->get_media_tab()->set_volume(0);

		if($title === NULL) {
			$title = $path;
		}

		$object->main_preview_web->get_webview()->evaluate('app.set_title(data)', function($res) {
			$object->log($res);
		}, [
			'data' => ['title' => $title]
		]);

		$minus_one = (-1);

		/*$right = $coordinates['left']+250;
		$bottom = $coordinates['top']-200;*/

		$box_values = [
			'display' => 1,
	        'set_rectangle' => [$coordinates['left'], $coordinates['top'], $minus_one, $minus_one],
			/*'rectangle_type' => [1, 1, 1, 1],*/
	        'set_width' => 250,
	        'set_height' => 200
		];

		$object->preview_container->get_layout()->set_box($box_values);


		$object->preview_container->get_layout()->animate((350/1000), [(59/100), (17/100), (5/10), (91/100)], [], async function() {
			$object->log('noobscript callback');
		});
	}

	public function hide_preview() {
		$box_values = [
			'width' => 0,
			'height' => 0
			/*'display' => 0*/
		];

		$object->preview_container->get_layout()->set_box($box_values);
		
		$object->preview_container->get_layout()->animate((350/1000), [(59/100), (17/100), (5/10), (91/100)], [], async function() {
			$object->main_preview_video->get_media_tab()->pause();
		});
	}

	public $indexing_dictioanry;

	private $callbacks;

	public function push_callback($callback) {
		$index = $this->callbacks->length;
		$callback_obj = [
			'id' => $index,
			'callback' => $callback
		];
		$this->callbacks[] = $callback_obj;
		return $index;
	}

	public function call_callback($callback_id) {
		$set_index = (-1);
		foreach($this->callbacks as $index => $callback_obj) {
			if($callback_obj['id'] == $callback_id) {
				$callback_obj['callback']();
				$callback_obj['id'] = NULL;
				$set_index = $index;
			}
		}
		if($set_index !== (-1)) {
			$object->splice($this->callbacks, $set_index, 1);
		}
		return ['result' => true];
	}

    public function receive_messages($message) {
    	$message_counter = $message['message_counter'];
    	delete $message['message_counter'];

    	$app_id = $message['app_id'];
    	delete $message['app_id'];
    	$action = $message['action'];
    	delete $message['action'];
    	$result = NULL;

		if($this->indexing_in_progress) {
			return [
	        	'message_counter' => $message_counter,
	        	'message' => $result,
	        	'stall' => true
	        ];
		}
		if($action == 'call_callback') {
			$result = $this->call_callback($message['callback_id']);
    	} else if($object->isset($message['callback_result'])) {
    		delete $message['callback_result'];

    		$send_callback = /*async*/ function($result_data) {
    			if(!$object->isset($result_data)) {
    				$result_data = NULL;
    			}
    			$object->send('app.receive_messages(data)', [
    				'data' => [
	    				'message_counter' => $message_counter, 
	    				'message' => $result_data
	    			]
    			]);

    			/*$object->dispose_parent($send_callback);*/
    		};

    		$result = $this->apps[$app_id][$action]($message, $send_callback);
    		return NULL;
    	} else {
	    	$result = $this->apps[$app_id][$action]($message);
	    }    
		if(!$object->isset($result)) {
			$result = NULL;
		}
        $res = $object->toJSON([
        	'message_counter' => $message_counter,
        	'message' => $result
        ]);
        return $res;
    }

    public $ws_connections = [];

	public function __add_ws_connection($ws_item) {
		$this->ws_connections[] = $ws_item;

		$self = $this;

		$ws_item->add_remove_callback(function() {
			$object->remove_item($self->ws_connections, $ws_item);
			if($object->isset($ws_item->user_object)) {
				$object->remove_item($ws_item->user_object['user_instance']->instances, $ws_item);
			}
		});

		$ws_item->main_properties = [
			'current_titlemedia_id' => NULL
		];

		$ws_item->add_response_callback(function($message) {
			if($message['action'] == 'sync_status_broadcast') {
				foreach($self->ws_connections as $ws_connection) {
					if(!$object->equals($ws_connection, $ws_item)) {
						$object->log('send to ');
						$object->log($ws_connection);
						$object->log($object->toJSON($message));
						$ws_connection->send([
        					'action' => 'set_sync_status',
        					'sync_status' => $message['sync_data']
        				]);
					}
				}
			}

		});
	}
}

$base_instance = new base();

?>
