<?

class cinema_app {

	private $data = NULL;

	public $base_instance = NULL;

	public function __construct($base_instance) {
		$this->base_instance = $base_instance;
		$this->data = $data->fetch('cinema');
		$this->data->statement = $data->statement;

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

		$init_string = 'CREATE TABLE IF NOT EXISTS folders (
id INTEGER primary key AUTOINCREMENT,
name text
);
CREATE TABLE IF NOT EXISTS movie_folder (
id INTEGER primary key AUTOINCREMENT,
movie_id INTEGER,
folder_id INTEGER
);
CREATE TABLE IF NOT EXISTS preferences (
id INTEGER primary key AUTOINCREMENT,
tv_shows_location TEXT,
movies_location TEXT
);
CREATE TABLE IF NOT EXISTS movies (
id INTEGER primary key AUTOINCREMENT,
filename TEXT,
filepath TEXT,
created DATETIME DEFAULT current_timestamp,
favorite BOOLEAN DEFAULT 0,
checked BOOLEAN DEFAULT 1,
oldpath TEXT,
deleted BOOLEAN default 0,
year DATETIME,
genre integer,
filesize TEXT
);
CREATE TABLE IF NOT EXISTS queue (
id INTEGER primary key AUTOINCREMENT,
movie_id INTEGER
);
CREATE TABLE IF NOT EXISTS watch_log (
id INTEGER primary key AUTOINCREMENT,
movie_id INTEGER,
created DATETIME DEFAULT current_timestamp
);
CREATE TABLE IF NOT EXISTS numrand (
id INTEGER primary key autoincrement,
particle_x double,
particle_y double,
particle_direction double,
phase_0 integer,
phase_1 integer,
phase_2 integer,
phase_3 integer,
phase_4 integer,
phase_5 integer,
phase_6 integer,
phase_7 integer,
phase_8 integer,
phase_9 integer,
phase_10 integer,
phase_11 integer,
phase_12 integer 
);
CREATE TABLE IF NOT EXISTS settings (
id INTEGER primary key autoincrement,
property TEXT,
value TEXT
);
CREATE TABLE IF NOT EXISTS genres (
id INTEGER primary key autoincrement,
name TEXT,
checked BOOLEAN DEFAULT 1
);
CREATE TABLE IF NOT EXISTS locations (
id INTEGER primary key AUTOINCREMENT,
location TEXT
)';


		$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);

		$this->live_indexing = new cinema_indexing($base_instance);
	}

	private $live_indexing;

	public function init_live_indexing($v=NULL) {
		$tv_locations = $object->map($this->get_sources(), function($e) {
			$location = $e['location'];
			if($object->strings->strpos($object->strings->strrev($location), '/') !== 0) {
				$location = $location.'/';
			}
			return $location;
		});

		$this->live_indexing->init($tv_locations);

		return ['result' => true];
	}

	public function has_run() {
		$query = 'SELECT * FROM settings WHERE property = ?';
		$rows = $this->data->get_rows($query, ['has_run']);
		if($rows->length == 0) {
			$v = [
				'property' => 'has_run',
				'value' => '1'
			];

			$insert = $this->data->statement->generate($v, 'settings');
			$this->data->_($insert, $v);
			return false;
		}
		return true;
	}

	public $extensions = ['m4v', 'mp4', 'mkv', 'avi', 'wmv', 'mov', 'flv', '3gp', 'mpg', 'ts', 'rm', 'swf'];

	public function index_movies($path) {
		$files_list = $files->list_files($path);
		$total_length = $files_list->length;
		$counter = 0;
		foreach($files_list as $file) {
			$full_path = $files->append_path($path, $file);
			if($files->is_dir($full_path)) {
				$this->index_movies($full_path);
			} else if($object->strings->strlen($file) > 0 && $object->strings->strlen($full_path) > 0 && $object->index_of($this->extensions, $files->get_extension($file)) != (-1) && $object->strpos($file, '.') != 0) {

				$query = 'SELECT * FROM movies WHERE filepath = ?';
				$rows = $this->data->get_rows($query, [$full_path]);


				$query = 'SELECT * FROM movies WHERE filename = ?';
				$rows_2 = $this->data->get_rows($query, [$file]);
				
				$episode_id = NULL;
				if($rows->length == 0 && $rows_2->length == 0) {
					$episode_id = $this->_movie([
						'path' => $full_path
					]);
					if($episode_id != NULL) {
						$this->update_movie([
							'id' => $episode_id,
							'filename' => $file
						]);
						$this->find_year_movie($episode_id, $full_path);
					}
				} else {
					if($rows->length > 0) {
						$episode_id = $rows[0]['id'];
					} else if($rows_2->length > 0) {
						$episode_id = $rows_2[0]['id'];
					}
					$this->update_movie([
						'id' => $episode_id,
						'filepath' => $full_path
					]);
				}
				if($episode_id != NULL) {
					$this->set_episode_index['ep_'.$episode_id] = true;
				}
			}
			$progress = $math->mult(($counter / $total_length), 100);
			$object->send('app.set_progress(data)', ['data' => $progress]);	
			$counter = $counter+1;
		}
	}

	public $set_episode_index = NULL;



	public function index_library($v=NULL) {
		$this->init_live_indexing(NULL);
	}

	public function index_library_manually($v=NULL) {
		$self = $this;
		if($this->base_instance->indexing_dictionary['cinema']) {
			return ['result' => 3];
		}
		$this->base_instance->indexing_dictionary['cinema'] = true;
		$this->base_instance->indexing_in_progress = true;
		$wrap = async function($callback) {
			$result = $self->index_library_sub();

			$callback();
			$object->send('app.cinema.settings_main.indexing_completed(data)', ['data' => $result]);
		};
		$wrap(function() {
			$self->base_instance->indexing_in_progress = false;
		});
		return ['result' => 1];
	}

	public function index_library_sub($v=NULL) {
		$files_index = [];
		$this->set_episode_index = ['test' => 1];
		delete $this->set_episode_index['test'];
		$sources = $this->get_sources();
		
		if($sources->length == 0) {
			return ['result' => 0];
		}

		foreach($sources as $source) {
			$location = $source['location'];

			if(!$files->is_readable($location)) {
				$this->base_instance->indexing_dictionary['cinema'] = false;
				return ['result' => -1];
			}
		}


		foreach($sources as $source) {
			$location = $source['location'];

			if($files->exists($location) && $files->is_dir($location)) {
				$this->index_movies($location);
			}
		}
		
		$query = 'SELECT * FROM movies';
		$episodes = $this->data->get_rows($query, []);
		if($this->set_episode_index != NULL && $object->values($this->set_episode_index)->length > 0) {
			foreach($episodes as $episode) {
				if($episode['id'] != NULL) {
					if(!$object->isset($this->set_episode_index['ep_'.$episode['id']])) {
						$query = 'DELETE FROM movies WHERE id = ?';
						$this->data->execute($query, [$episode['id']]);
					}
				}
			}
		}
		$this->base_instance->indexing_dictionary['cinema'] = false;
		return ['result' => 1];
	}

	public function _pref($v) {
		$query = 'DELETE FROM preferences';
		$this->data->execute($query, []);
		$insert = $this->data->statement->generate($v, 'preferences');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function _location($v) {
		$insert = $this->data->statement->generate($v, 'locations');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function get_sources($v=NULL) {
		$query = 'SELECT tv_shows_location, movies_location FROM preferences';
		$preferences = $this->data->get_rows($query, []);
		$query = 'SELECT * FROM locations';
		$locations = $this->data->get_rows($query, []);
		if($preferences->length > 0) {
			$locations = $object->concat([[
				'id' => 0,
				'location' => $preferences[0]['tv_shows_location']
			]], $locations);
		}
		return $locations;
	}

	public function set_sources($v) {
		$locations = $v['locations'];
		$location_ids = [];
		foreach($locations as $key => $location) {
			if($object->isset($location['id']) && $location['id'] == 0) {
				$this->_pref([
					'tv_shows_location' => $location['location']
				]);
			} else {
				$location_ids[] = $this->_location($location);
			}
		}
		foreach($locations as $location) {
			if($object->isset($location['id']) && $object->index_of($location_ids, $location['id']) == (-1)) {
				$location_ids[] = $location['id'];
			}
		}
		$sources = $this->get_sources();
		foreach($sources as $source) {
			if($object->index_of($location_ids, $source['id']) == (-1)) {
				$query = 'DELETE FROM locations WHERE id = ?';
				$this->data->execute($query, [$source['id']]);
			}
		}
		$this->init_live_indexing();
		return ['result' => 1];
	}

	public function _movie($v) {
		$path = $v['path'];
		if($object->strings->strlen($path) > 0) {
			$query = 'SELECT id FROM movies WHERE filepath = ?';
			$rows = $this->data->get_rows($query, [$path]);
			$id = NULL;
			if($rows->length > 0) {
				$id = $rows[0]['id'];
			}
			$v = [
				'filepath' => $path
			];
			if($id != NULL) {
				$v['id'] = $id;
			}

			$insert = $this->data->statement->generate($v, 'movies');
			$this->data->_($insert, $v);
			$id = $this->data->last_id($v);
			return $id;
		}
		return NULL;
	}

	public function find_year_movie($id, $filepath=NULL) {
		if($filepath == NULL) {
			return NULL;
		}
		$match = $object->regex->preg_match('[0-9]{4}', $filepath);
		$found = false;
		foreach($match as $location => $match) {
			if(!$found) {
				$found = true;
				$year = $match['value'];
				$v = [
					'id' => $id,
					'year' => $year
				];
				$insert = $this->data->statement->generate($v, 'movies');
				$this->data->_($insert, $v);
			}
		}
		return NULL;
	}

	public function update_movie($v) {
		$insert = $this->data->statement->generate($v, 'movies');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}
	
	public function add_movie_to_folder($v) {
		$this->remove_movie_from_folder($v);
		$insert = $this->data->statement->generate($v, 'movie_folder');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function remove_movie_from_folder($v) {
		$query = 'DEL FROM movie_folder WHERE movie_id = ? AND folder_id = ?';
		$this->data->execute($query, [$v['movie_id'], $v['folder_id']]);
		return ['result' => 1];
	}

	public function remove_from_queue($v) {
		$query = 'DEL FROM queue WHERE movie_id = ?';
		$this->data->execute($query, [$v['movie_id']]);
		return ['result' => 1];
	}

	public function add_to_queue($v) {
		$query = 'DEL FROM queue WHERE movie_id = ?';
		$this->data->execute($query, [$v['movie_id']]);
		$insert = $this->data->statement->generate($v, 'queue');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function reset($v) {
		$this->data->execute('DELETE FROM folders', []);
		$this->data->execute('DELETE FROM movie_folder', []);
		$this->data->execute('DELETE FROM movies', []);
		$this->data->execute('DELETE FROM queue', []);
		$this->data->execute('DELETE FROM watch_log', []);
		return ['result' => 1];
	}

	public function delete_history($v=NULL) {
		$query = 'DELETE FROM watch_log';
		$this->data->execute($query, []);
		return true;
	}

	public function toggle_movie($v) {
		$insert = $this->data->statement->generate($v, 'movies');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	

	public function preferences($v) {
		$insert = $this->data->statement->generate($v, 'preferences');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function play_movie($v) {
		$query = 'SELECT * FROM movies WHERE id = ?';
		$row = $this->data->get_row($query, [$v['id']]);
		if($row->length > 0 && $object->isset($row['filepath'])) {
			$path = $row['filepath'];

			$this->base_instance->apps['player']->play(['path' => $path]);

			$v = [
				'movie_id' => $v['id']
			];
			$insert = $this->data->statement->generate($v, 'watch_log');
			$this->data->_($insert, $v);
			return $path;
		}
		return NULL;
	}


	public function reset_years($v) {
		$query = 'SELECT * FROM movies WHERE year IS NULL';
		$rows = $this->data->get_rows($query, []);
		foreach($rows as $row) {
			$this->find_year_movie($row['id'], $row['filename']);
		}
		return ['result' => 1];
	}

	public function save_setting($v) {
		$query = 'DEL FROM settings WHERE property = ?';
		$this->data->execute($query, [$v['property']]);
		$insert = $this->data->statement->generate($v, 'settings');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function update_genre($v) {
		$insert = $this->data->statement->generate($v, 'genres');
		$this->data->_($insert, $v);
		return ['result' => 1];
	}

	public function del_genre($v) {
		$query = 'DEL FROM genres WHERE id = ?';
		$this->data->execute($query, [$v['id']]);
		$query = 'UPDATE movies SET genre = NULL WHERE genre = ?';
		$this->data->execute($query, [$v['id']]);
		return ['result' => 1];
	}

	public function queue($v) {
		$query = 'SELECT movies.* FROM movies, queue WHERE movies.id = queue.movie_id ORDER BY queue.id ASC';
		return $this->data->get_rows($query, []);
	}

	public function get_genres($v) {
		$query = 'SELECT * FROM genres';
		return $this->data->get_rows($query, []);
	}

	public function get_settings($v) {
		$query = 'SELECT * FROM settings';
		return $this->data->get_rows($query, []);
	}

	public function clear_queue($v) {
		$query = 'DEL FROM queue';
		$this->data->execute($query, []);
		return ['result' => 1];
	}

	public function del_movie($v) {
		$id = $v['id'];
		$query = 'DEL FROM movies WHERE id = ?';
		$this->data->execute($query, [$id]);
		return ['result' => 1];
	}

	public function favorite_movie($v) {
		$insert = $this->data->statement->generate($v, 'movies');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function del_folder($v) {
		$query = 'DEL FROM folders WHERE id = ?';
		$this->data->execute($query, [$v['id']]);
	}

	public function folder($v) {
		$insert = $this->data->statement->generate($v, 'folders');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return $id;
	}

	public function get_favorites($v) {
		$query = 'SELECT * FROM movies WHERE favorite = 1  ORDER BY movies.filename ASC';
		return $this->data->get_rows($query, []);
	}

	public function get_folder($v) {
		$id = $v['id'];
		$query = 'SELECT * FROM folders WHERE id = ?';
		return $this->data->get_rows($query, [$id]);
	}

	public function get_movie($v) {
		$query = 'SELECT * FROM movies WHERE id = ?';
		return $this->data->get_row($query, [$v['id']]);
	}

	public function get_movies($v) {
		$query = 'SELECT * FROM movies WHERE deleted = 0 ORDER BY filename ASC';
		return $this->data->get_rows($query, []);
	}

	public function get_movie_by_path($path) {
		$query = 'SELECT * FROM movies WHERE filepath = ?';
		return $this->data->get_row($query, [$path]);
	}

	public function toggle_movie_by_path($path) {
		$movie = $this->get_movie_by_path($path);
		if($movie != NULL) {
			$checked_value = 1;
			if($movie['checked'] == 1) {
				$checked_value = 0;
			}
			$v = [
				'id' => $movie['id'],
				'checked' => $checked_value 
			];
			$this->update_movie($v);
		}
	}

	public function get_folders($v) {
		$query = 'SELECT * FROM folders';
		$rows = $this->data->get_rows($query, []);
		return $rows;
	}

	public function get_folder_movies($v) {
		$query = 'SELECT movies.* FROM movie_folder, movies WHERE movie_folder.movie_id = movies.id AND movie_folder.folder_id = '.$v['folder_id'].' ORDER BY movies.filename ASC';
		return $this->data->get_rows($query, $v);
	}

	public function get_trash($v) {
		$query = 'SELECT * FROM movies WHERE deleted = 1 ORDER BY filepath ASC';
		return $this->data->get_rows($query, []);
	}

	public function get_preferences($v) {
		$query = 'SELECT tv_shows_location, movies_location FROM preferences';
		$rows = $this->data->get_rows($query, []);
		if($rows->length == 0) {
			return [];
		}
		return $rows[0];
	}

	public function get_recently_added($v) {
		$date = $date->get_date('default', 0, -3, 0);
		$query = 'SELECT * FROM movies WHERE deleted = 0 AND created > ? ORDER BY movies.filepath ASC';
		return $this->data->get_rows($query, [$date]);
	}

	public function get_recently_not_watched($v) {
		$date = $date->get_date('default', -1, 0, 0);
		$query = 'SELECT * FROM movies WHERE deleted = 0 AND (SELECT COUNT(*) FROM watch_log WHERE watch_log.movie_id = movies.id) = 0 UNION SELECT movies.* FROM movies, watch_log WHERE deleted = 0 AND movies.id = watch_log.movie_id AND watch_log.created < ? ORDER BY movies.filepath ASC';
		return $this->data->get_rows($query, [$date]);
	}

	public function get_recently_watched($v) {
		$date = $date->get_date('default', -1, 0, 0);
		$query = 'SELECT movies.* FROM movies, watch_log WHERE deleted = 0 AND movies.id = watch_log.movie_id AND watch_log.created > ? ORDER BY watch_log.created DESC';
		return $this->data->get_rows($query, [$date]);
	}

	public function _numrand($v) {
		$query = 'DEL FROM numrand';
		$this->data->execute($query, []);
		$insert = $this->data->statement->generate($v, 'numrand');
		$this->data->_($insert, $v);
		$id = $this->data->last_id($v);
		return ['id' => $id];
	}

	public function get_state($v) {
		$query = 'SELECT * FROM numrand ORDER BY id DESC LIMIT 1';
		$rows = $this->data->get_rows($query, []);
		if($rows->length == 0) {
			return [];
		}
		return $rows[0];
	}

	public function play_random_movie($v=NULL) {
		$object->log('folder id');
		$object->log($v['folder_id']);
		if($v['folder_id'] == (-1)) {
			return $this->get_recently_not_watched(NULL);
		}
		$date = $date->get_date('default', 0, -6, 0);
		$query = 'SELECT movies.* FROM movies, movie_folder WHERE movie_folder.movie_id = movies.id AND movie_folder.folder_id = '.$v['folder_id'].' AND movies.deleted = 0 AND (SELECT COUNT(*) FROM watch_log WHERE watch_log.movie_id = movies.id) = 0 UNION SELECT movies.* FROM movies, watch_log, movie_folder WHERE movie_folder.movie_id = movies.id AND movie_folder.folder_id = '.$v['folder_id'].' AND deleted = 0 AND movies.id = watch_log.movie_id AND watch_log.created < ? ORDER BY movies.filepath ASC';
		$object->log($query);
		$rows = $this->data->get_rows($query, [$date]);
		return $rows;
	}
}

?>