<?php

/**
 * Fired during plugin activation
 *
 * @link       https://ristrettoapps.com
 * @since      1.0.0
 *
 * @package    Spawnster
 * @subpackage Spawnster/includes
 */

/**
 * Fired during plugin activation.
 *
 * This class defines all code necessary to run during the plugin's activation.
 *
 * @since      1.0.0
 * @package    Spawnster
 * @subpackage Spawnster/includes
 * @author     Ristretto Apps
 */
class Spawnster_Activator {

	/**
	 * Short Description. (use period)
	 *
	 * Long Description.
	 *
	 * @since    1.0.0
	 */
	public static function activate() {
		global $wpdb;

		$vector_table_name           = Spawnster::get_vector_table_name();
		$post_vector_table_name      = Spawnster::get_post_vector_table_name();
		$post_summary_table_name     = Spawnster::get_post_summary_table_name();
		$charset_collate             = $wpdb->get_charset_collate();
		$storage_engine              = Spawnster::get_storage_engine();
		$binary_code_length_in_bytes = ceil( Spawnster::get_vector_dimension() / 8 );

		$queries   = array();
		$queries[] = "CREATE TABLE $vector_table_name (
			ID INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
			vector JSON,
			normalized_vector JSON,
			magnitude DOUBLE,
			binary_code BINARY($binary_code_length_in_bytes),
			created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
			INDEX idx_binary_code (binary_code)
		) ENGINE=$storage_engine $charset_collate;";
		$queries[] = "CREATE TABLE $post_vector_table_name (
			post_id BIGINT(20) UNSIGNED NOT NULL,
			vector_id INT UNSIGNED NOT NULL
		) ENGINE=$storage_engine $charset_collate;";
		$queries[] = "CREATE TABLE $post_summary_table_name (
			ID BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
			post_id BIGINT(20) UNSIGNED NOT NULL,
			summary TEXT NOT NULL,
			PRIMARY KEY (id),
			UNIQUE KEY post_id (post_id)
		) ENGINE=$storage_engine $charset_collate;";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $queries );

		$queries   = array();
		$queries[] = <<<SQL
				ALTER TABLE $post_vector_table_name
				ADD CONSTRAINT fk_{$post_vector_table_name}_{$wpdb->prefix}posts
				FOREIGN KEY (post_id)
				REFERENCES {$wpdb->prefix}posts(ID)
				ON DELETE CASCADE
SQL;
		$queries[] = <<<SQL
				ALTER TABLE $post_vector_table_name
				ADD CONSTRAINT fk_{$post_vector_table_name}_$vector_table_name
				FOREIGN KEY (vector_id)
				REFERENCES $vector_table_name(ID)
				ON DELETE CASCADE
SQL;
		$queries[] = 'DROP FUNCTION IF EXISTS SPAWNSTER_COSIM';
		$queries[] = <<<SQL
				CREATE FUNCTION SPAWNSTER_COSIM(vector1 JSON, vector2 JSON) RETURNS DOUBLE DETERMINISTIC
				BEGIN
					DECLARE dotProduct DOUBLE DEFAULT 0.0;
					DECLARE normA DOUBLE DEFAULT 0.0;
					DECLARE normB DOUBLE DEFAULT 0.0;
					DECLARE len INT DEFAULT JSON_LENGTH(vector1);
					DECLARE i INT DEFAULT 0;
					DECLARE v1 DOUBLE;
					DECLARE v2 DOUBLE;

					WHILE i < len DO
							SET v1 = CAST(JSON_UNQUOTE(JSON_EXTRACT(vector1, CONCAT('$[', i, ']'))) AS DOUBLE);
							SET v2 = CAST(JSON_UNQUOTE(JSON_EXTRACT(vector2, CONCAT('$[', i, ']'))) AS DOUBLE);

							SET dotProduct = dotProduct + (v1 * v2);
							SET normA = normA + (v1 * v1);
							SET normB = normB + (v2 * v2);

							SET i = i + 1;
					END WHILE;

					RETURN dotProduct / (SQRT(normA) * SQRT(normB));
				END
SQL;

		foreach ( $queries as $index => $query ) {
			$wpdb->query( $query );

			if ( 3 === $index ) {
				update_option( 'spawnster_sql_cosim_available', '' === $wpdb->last_error );
			}

			if ( $wpdb->last_error ) {
				error_log( esc_html( $wpdb->last_error ) );
			}
		}

		add_option( 'spawnster_resume_scheduled_jobs', time() );
	}

}
