<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * END LICENSE
 *
 * Test to see for big strings which how long various string concatenation
 * operations take.
 *
 * @author Chris Pollett chris@pollett.orgs
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\tests;

use seekquarry\yioop\configs as C;
use seekquarry\yioop\library as L;
use seekquarry\yioop\models as M;

if (isset($_SERVER['DOCUMENT_ROOT']) && strlen($_SERVER['DOCUMENT_ROOT']) > 0) {
    echo "BAD REQUEST";
    exit();
}
/**
 * This script inserts 500 users into the database so that one can
 * test UI of Yioop in a scenario that has a moderate number of users.
 * It then insert groups for these users
 */
/**
 * Calculate parent directory of script
 * @ignore
 */
define("seekquarry\\yioop\\configs\\PARENT_DIR", substr(
    dirname(realpath($_SERVER['PHP_SELF'])), 0,
    -strlen("/tests")));
/**
 * Calculate base directory of script
 * @ignore
 */
define("seekquarry\\yioop\\configs\\BASE_DIR", C\PARENT_DIR . "/src");
require_once C\BASE_DIR . '/configs/Config.php';
C\nsconddefine("ME_NUM_USERS", 500);
C\nsconddefine("ME_NUM_GROUPS", 100);
C\nsconddefine("ME_NUM_THREADS", 100);
C\nsconddefine("ME_NUM_ROLES", 100);
C\nsconddefine("ME_NUM_MIXES", 100);
C\nsconddefine("ME_NUM_RESOURCES_IMPRESSION", 15);
C\nsconddefine("USE_RANDOM_TIMESTAMP", true);
C\nsconddefine('ONE_MINUTE_SECONDS', 60);
C\nsconddefine('ONE_HOUR_SECONDS', 3600);
C\nsconddefine('ONE_MONTH_SECONDS', 2592000);
C\nsconddefine('ONE_YEAR_SECONDS', 31536000);
C\nsconddefine('TWO_YEARS_SECONDS', 2 * 31536000);
C\nsconddefine('THREE_YEARS_SECONDS', 3 * 31536000);
C\nsconddefine('FOUR_YEARS_SECONDS', 4 * 31536000);
C\nsconddefine('FIVE_YEARS_SECONDS', 5 * 31536000);
C\nsconddefine('NUMBER_OF_IMPRESSIONS', 20000);

function getNextTimestamp()
{
    static $previous_timestamp = null;
    $current_time = time();
    $target_count = C\NUMBER_OF_IMPRESSIONS;
    if ($previous_timestamp === null) {
        $start_min = $current_time - C\FIVE_YEARS_SECONDS;
        $start_max = $current_time - C\THREE_YEARS_SECONDS;
        $previous_timestamp = rand($start_min, $start_max);
    }
    $remaining_time = $current_time - $previous_timestamp;
    if ($remaining_time < C\ONE_HOUR_SECONDS) {
        return null;
    }
    $average_gap = $remaining_time / $target_count;
    $min_gap = max(C\ONE_HOUR_SECONDS, (int)($average_gap / 2));
    $max_gap = min(C\ONE_MONTH_SECONDS, (int)($average_gap * 2));
    if ($min_gap > $max_gap) {
        $min_gap = $max_gap;
    }
    $increment = rand($min_gap, $max_gap);
    $previous_timestamp += $increment;
    if ($previous_timestamp > $current_time) {
        $previous_timestamp = $current_time;
    }
    return $previous_timestamp;
}
$user_model = new M\UserModel();
$group_model = new M\GroupModel();
$wiki_model = new M\WikiModel();
$feed_model = new M\FeedModel();
//Add lots of users
$user_ids = [];
for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
    echo "Adding User $i\n";
    $id = $user_model->addUser("User$i", "test", "First$i", "Last$i",
        "user$i@email.net", C\ACTIVE_STATUS);
    if ($id === false) {
        echo "Problem inserting user into DB, aborting...\n";
        exit(1);
    }
    $personal_group_name = C\PERSONAL_GROUP_PREFIX . $id;
    if ($group_model->getGroupId($personal_group_name) < 0) {
        $input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
        $group_model->addGroup($personal_group_name, $id, C\INVITE_ONLY_JOIN,
            C\ACTIVE_STATUS, C\NON_VOTING_GROUP, C\FOREVER, 0,
            skip_impression: true, input_timestamp: $input_timestamp);
    }
    $user_ids[$i] = $id;
}
// add lots of groups
$group_ids = [];
for ($i = 0; $i < C\ME_NUM_GROUPS; $i++) {
    echo "Creating Group $i\n";
    $input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
    $group_ids[$i] = $group_model->addGroup("Group$i", $user_ids[$i],
        C\PUBLIC_JOIN, C\GROUP_READ_WIKI, skip_impression : true,
        input_timestamp: $input_timestamp);
}
// add lots of users to groups (everyone belongs to at least group 1)
for ($i = 0; $i < C\ME_NUM_GROUPS; $i++) {
    $user_id = $user_ids[$i];
    for ($j = 1; $j < ($i/10) + 1; $j++) {
        if ($j != $i) {//by above user $i is owner (and so in) group $i
            echo "Adding User $i (user id $user_id) to ".
                "Group $j (group id {$group_ids[$j]})\n";
            $group_model->addUserGroup($user_id, $group_ids[$j],
                C\ACTIVE_STATUS);
        }
    }
}
$impression_model = new M\ImpressionModel();
// add lots of threads and comments (hence, also impressions) to group 1
for ($i = 0; $i < C\ME_NUM_THREADS; $i++) {
    $user_id = $user_ids[$i];
    $title = "My first thread: User $user_id";
    echo "Adding User $user_id  Group {$group_ids[1]} Thread\n";
    $input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
    $parent_id = $feed_model->addGroupItem(0, $group_ids[1], $user_id,
        $title, "I really like this thread, User:$user_id",
        input_timestamp: $input_timestamp);
    $title = "--" . $title;
    for ($j = 0; $j < ($i / 10) + 1; $j++) {
        $comment_user_id = $user_ids[$j];
        $input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
        $impression_model->add($comment_user_id, $parent_id,
            C\THREAD_IMPRESSION, time: $input_timestamp);
        $impression_model->add($comment_user_id, $group_ids[1],
            C\GROUP_IMPRESSION, time: $input_timestamp);
        $feed_model->addGroupItem($parent_id, $group_ids[1], $comment_user_id,
            $title, "I totally agree with you, User:$comment_user_id");
    }
}
// add lots of roles
$role_model = new M\RoleModel();
$user_id = $user_ids[2];
for ($i = 0; $i < C\ME_NUM_ROLES; $i++) {
    echo "Creating Role $i\n";
    $role_model->addRole("Role$i");
    $role_id =  $role_model->getRoleId("Role$i");
    $role_model->addUserRole($user_id, $role_id);
}
$crawl_model = new M\CrawlModel();
$mix = [];
$mix['TIMESTAMP'] = time();
$mix['FRAGMENTS'] = [];
$mix['OWNER_ID'] = C\ROOT_ID;
$mix['PARENT'] = -1;
for ($i = 0; $i < C\ME_NUM_MIXES; $i++) {
    echo "Creating Crawl Mix $i\n";
    $mix['TIMESTAMP']++;
    $mix['NAME'] = "Mix$i";
    $crawl_model->setCrawlMix($mix);
}
// add wiki page to group 1
$page = <<< 'EOD'
page_type=media_list

page_alias=

page_border=solid-border

toc=true

title=

author=

robots=

description=

alternative_path=

page_header=

page_footer=

sort=aname

update_description=files-and-folders

END_HEAD_VARS
==This is test page.==
EOD;
$page_content = str_replace("'", "&#039;", $page);
$page_name = "Test";
echo "Adding wiki page $page_name to group $group_ids[0]...\n";
$input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
$page_id = $wiki_model->setPageName($user_ids[0], $group_ids[0], $page_name,
    $page_content, "en-US", "Creating test wiki page",
    "{$page_name} Wiki Page Created!", "Discuss the page in this thread!",
    input_timestamp: $input_timestamp);
echo "Added the wiki page...\n";
echo "Creating movies folder and adding dummy mp4 resources\n";
$resources = [];
$folders_path = [];
// create movie folder in the wiki page
$folders = $wiki_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
    "movies", true);
// add resources to the movies subfolder
$movies = [
    "The 355.mp4",
    "The Legend of La Llorona.mp4",
    "The Commando.mp4",
    "American Siege.mp4",
    "Scream.mp4",
    "Hotel Transylvania Transformania.mp4",
    "Shattered.mp4",
    "The Royal Treatment.mp4",
    "Redeeming Love.mp4",
    "The Kings Daughter.mp4",
    "The Tiger Rising.mp4",
    "Hellblazers.mp4",
    "The Fallout.mp4",
    "Home Team.mp4",
    "The Ice Age Adventures of Buck Wild.mp4",
    "Clean.mp4",
    "Sundown.mp4",
    "Jackass Forever.mp4",
    "Moonfall.mp4",
    "Last Looks.mp4",
    "The Long Night.mp4",
    "Kimi.mp4",
    "Shut In.mp4",
    "Death on the Nile.mp4",
    "Marry Me.mp4",
    "Blacklight.mp4",
    "I Want You Back.mp4",
    "Tall Girl 2.mp4",
    "The Sky Is Everywhere.mp4",
    "The In Between.mp4",
    "Fistful of Vengeance.mp4",
    "Uncharted.mp4",
    "Dog.mp4",
    "Texas Chainsaw Massacre.mp4",
    "The Cursed.mp4",
    "A Fairy Tale After All.mp4",
    "Cyrano.mp4",
    "Studio 666.mp4",
    "A Madea Homecoming.mp4",
    "No Exit.mp4",
    "Gasoline Alley.mp4",
    "The Batman.mp4",
    "After Yang.mp4",
    "Fresh.mp4",
    "A Day to Die.mp4",
    "The Adam Project.mp4",
    "Turning Red.mp4",
    "Tysons Run.mp4",
    "Rescued by Ruby.mp4",
    "The Outfit.mp4",
    "Deep Water.mp4",
    "Cheaper by the Dozen.mp4",
    "Windfall.mp4",
    "X.mp4",
    "Umma.mp4",
    "Alice.mp4",
    "Master.mp4",
    "Measure of Revenge.mp4",
    "The Lost City.mp4",
    "Everything Everywhere All at Once.mp4"
];
$resources[] = $movies;
$folders_path[] = $folders;
foreach ($movies as $movie) {
    $wiki_model->setPageResource($movie, "This is test data", $group_ids[0],
        $page_id, "movies");
}
echo "Creating web_series folder and adding dummy mp4 resources\n";
// create web_series folder in the wiki page
$folders = $wiki_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
    "web_series", true);
// add resources to the web_series subfolder
$web_series = [
    "Unforgotten Season 2.mp4",
    "The Devils Hour Season 1.mp4",
    "Indian Predator Murder in a Courtroom.mp4",
    "If Only.mp4",
    "Flames Season 3.mp4",
    "Jhansi.mp4",
    "Dubai Bling.mp4",
    "The Mysterious Benedict Society Season 2.mp4",
    "Sumo Do, Sumo Dont!.mp4",
    "Star Wars Tales of the Jedi.mp4",
    "Shadow Detective.mp4",
    "Tripling Season 3.mp4",
    "The Serpent Queen.mp4",
    "The Peripheral.mp4",
    "From Scratch.mp4",
    "Four More Shots Please! Season 3.mp4",
    "Barbarians Season 2.mp4",
    "Notre-Dame.mp4",
    "Shantaram.mp4",
    "Mismatched Season 2.mp4",
    "Good Bad Girl.mp4",
    "Everything Calls for Salvation.mp4",
    "The Watcher.mp4",
    "The Playlist.mp4",
    "Exception Season 1.mp4",
    "Rookie Cops.mp4",
    "Big Shot Season 2.mp4",
    "Belascoarán, Pl Season 1.mp4",
    "Werewolf by Night.mp4",
    "The Midnight Club.mp4",
    "Man on Pause.mp4",
    "Derry Girls Season 3.mp4",
    "Conversations with a Killer The Jeffrey Dahmer Tapes.mp4",
    "Aashiqana Season 2.mp4",
    "Shipwreck Hunters Australia.mp4"
];
$resources[] = $web_series;
$folders_path[] = $folders;
foreach ($web_series as $series) {
    $wiki_model->setPageResource($series, "This is test data", $group_ids[0],
        $page_id, "web_series");
}
echo "Creating books folder and adding dummy pdf resources\n";
// create books folder in the wiki page
$folders = $wiki_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
    "books", true);
// add resources to the books subfolder
$books = [
    "Book Lovers.pdf",
    "Gallant.pdf",
    "Daughter of the Moon Goddess.pdf",
    "Book of Night.pdf",
    "The Girl Who Fell Beneath the Sea.pdf",
    "I Kissed Shara Wheeler.pdf",
    "House of Sky and Breath.pdf",
    "A Magic Steeped in Poison.pdf",
    "Love on the Brain.pdf",
    "Only a Monster.pdf",
    "This Woven Kingdom.pdf",
    "Delilah Green Doesnt Care.pdf",
    "Portrait of a Thief.pdf",
    "The Paris Apartment.pdf",
    "Foul Lady Fortune.pdf",
    "Bloodmarked.pdf",
    "Belladonna.pdf",
    "Ophelia After All.pdf",
    "Violet Made of Thorns.pdf",
    "Carrie Soto Is Back.pdf",
    "Hook, Line, and Sinker.pdf",
    "The MaidThe Maid.pdf",
    "A Far Wilder Magic.pdf",
    "Sea of Tranquility.pdf",
    "The Book of Cold Cases.pdf",
    "All My Rage.pdf",
    "Kaikeyi.pdf",
    "How High We Go in the Dark.pdf",
    "The Sunbearer Trials.pdf",
    "Hotel Magnifique.pdf",
    "What Moves the Dead.pdf",
    "Stuck with You.pdf",
    "Below Zero.pdf",
    "The House Across the Lake.pdf",
    "Nettle & Bone.pdf",
    "A Million to One.pdf",
    "An Arrow to the Moon.pdf",
    "Something Wilder.pdf",
    "Anatomy: A Love Story.pdf",
    "The Final Gambit.pdf",
    "The City of Dusk.pdf",
    "The Ivory Key.pdf",
    "So This Is Ever After.pdf",
    "The Book Eaters.pdf",
    "The Red Palace.pdf",
    "The Stardust Thief.pdf",
    "She Gets the Girl.pdf",
    "Weather Girl.pdf",
    "The Bone Spindle.pdf"
];
$resources[] = $books;
$folders_path[] = $folders;
foreach ($books as $book) {
    $wiki_model->setPageResource($book, "This is test data", $group_ids[0],
        $page_id, "books");
}
echo "Creating users impression with random resources\n";
for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
    $user_id = $user_ids[$i];
    for ($j = 0; $j < C\ME_NUM_RESOURCES_IMPRESSION; $j++) {
        $resource_type = rand(0,2);
        $resource_index = rand(0, count($resources[$resource_type]) - 1);
        $resource_name = $resources[$resource_type][$resource_index];
        echo "Creating RESOURCE_IMPRESSION for user $user_id with resource" .
            " $resource_name\n";
        $resource_id = unpack('n', md5($group_ids[0] . $page_id .
            $folders_path[$resource_type][1] . "/" . $resource_name, true))[1];
        $input_timestamp = C\USE_RANDOM_TIMESTAMP ? getNextTimestamp() : -1;
        $impression_model->add($user_id, $resource_id,
            C\RESOURCE_IMPRESSION, time: getNextTimestamp());
    }
}
