<?php


namespace Fliegerlogin\DbSchema;


use Fliegerlogin\Options;

class DbSchema implements IDbSchema {

	private static $table_prefix = 'fliegerlogin_';
	private static $db_version = 2;
	private static $wpdb = null;

	public static function init(): void {
		self::$wpdb = $GLOBALS['wpdb'];
		self::install();
	}

	public static function install(): void {
		if (Options::getInstalledDbVersion() === self::getDbVersion()) {
			return;
		}

		Users::install();

		Options::setInstalledDbVersion(self::getDbVersion());
	}

	public static function uninstall(): void {
		Users::uninstall();
	}

	/**
	 * Gets table prefix for tables and columns of this plugin.
	 * @return string
	 */
	public static function getTablePrefix(): string {
		return self::$table_prefix;
	}

	/**
	 * Gets the current database version.
	 *
	 * Returns an int on purpose: Options::getInstalledDbVersion() is typed ?int,
	 * and while this returned a string the equality check in install() was never
	 * true - the migration ran on every request instead of once.
	 */
	public static function getDbVersion(): int {
		return self::$db_version;
	}

	/**
	 * Gets the wordpress database object.
	 * @return \wpdb
	 */
	public static function getWpdb(): \wpdb {
		return self::$wpdb;
	}

	/**
	 * Appends a column to a table.
	 * @param string $table
	 * @param string $name
	 * @param string $definition
	 * @return bool
	 */
	public static function addColumn(string $table, string $name, string $definition): bool {
		return self::getWpdb()->query(
			'ALTER TABLE `' . $table . '` ADD COLUMN `' . $name . '` ' . $definition . ';'
		);
	}

	/**
	 * Removes a column from a table.
	 * @param string $table
	 * @param string $name
	 * @return bool
	 */
	public static function removeColumn(string $table, string $name): bool {
		return self::getWpdb()->query(
			'ALTER TABLE `' . $table . '` DROP COLUMN `' . $name . '`;'
		);
	}

	/**
	 * Adds a unique key to a table
	 * @param string $table
	 * @param string $name
	 * @param string[]  $columns
	 * @return bool
	 */
	public static function addUnique(string $table, string $name, array $columns): bool {
		return self::getWpdb()->query(
			'ALTER TABLE `' . $table . '` ADD CONSTRAINT `' . $name . '` UNIQUE (`' . implode('`,`', $columns) . '`);'
		);
	}

	/**
	 * Renames a column, keeping its contents.
	 *
	 * MySQL wants the full definition repeated in a CHANGE, so callers have to
	 * pass it again - there is no shorter portable form.
	 */
	public static function renameColumn(string $table, string $from, string $to, string $definition): bool {
		return self::getWpdb()->query(
			'ALTER TABLE `' . $table . '` CHANGE `' . $from . '` `' . $to . '` ' . $definition . ';'
		);
	}

	/**
	 * Whether a column exists.
	 *
	 * Compares the names in PHP rather than with SHOW COLUMNS ... LIKE: the
	 * underscore is a LIKE wildcard, and every name here contains one.
	 */
	public static function columnExists(string $table, string $name): bool {
		$columns = self::getWpdb()->get_col('SHOW COLUMNS FROM `' . $table . '`');

		return is_array($columns) && in_array($name, $columns, true);
	}

	/**
	 * Whether an index of that name exists. Key_name is the third column of
	 * SHOW INDEX, and one index can span several rows.
	 */
	public static function indexExists(string $table, string $name): bool {
		$names = self::getWpdb()->get_col('SHOW INDEX FROM `' . $table . '`', 2);

		return is_array($names) && in_array($name, $names, true);
	}

	/**
	 * Removes an index from a table
	 * @param string $table
	 * @param string $name
	 * @return bool
	 */
	public static function removeIndex(string $table, string $name): bool {
		return self::getWpdb()->query(
			'ALTER TABLE `' . $table . '` DROP INDEX `' . $name . '`;'
		);
	}

}