<?php

namespace App\Services;

use App\Browser\BrowserJob;
use Cache;
use Exception;

class BrowserJobsInstances {

    /**
     * A dictionnary of all job instances by their jobId
     * @var array Dictionnary of BrowserJob by their jobId
     */
    private $jobInstancesByJobId = [];

    /**
     * Index all jobs in the app/Browser/Jobs directory
     * and store them in the cache
     * @return void
     */
    private function indexJobsClassesById(): void
    {
        // Read all directories in app/Browser/jobs,
        // foreach directory, get the file named {directoryName}Job.php if it exists
        $folders = scandir(app_path('Browser/Jobs'));
        $files = [];
        foreach ($folders as $folder) {
            if ($folder == '.' || $folder == '..') {
                continue;
            }
            if (is_dir(app_path('Browser/Jobs/' . $folder))) {
                $potentialFileName = $folder . '/' . $folder . 'Job.php';
                if (file_exists(app_path('Browser/Jobs/' . $potentialFileName))) {
                    $files[] = $potentialFileName;
                }
            }
        }

        // Make a dictionnary of the id of the job as the key and the job class instance as value
        foreach ($files as $file) {
            $className = str_replace('.php', '', $file);
            $className = str_replace('/', '\\', $className);
            $fullClassName = 'App\Browser\Jobs\\' . $className;
            $jobInstance = new $fullClassName();
            $jobId = $jobInstance->jobId;
            Cache::put('jobClass' . $jobId, $fullClassName); // Met le nom de la classe en cache
            $this->jobInstancesByJobId[$jobId] = $jobInstance;
        }
    }

    /**
     * Get an instance of a job by it's jobId
     * @param mixed $jobId The ID of the job in the database
     * @return BrowserJob
     */
    public function getJobInstance($jobId): BrowserJob
    {
        try {
            return $this->jobInstancesByJobId[$jobId];
        } catch (Exception $e) {
            return $this->getNewJobInstance($jobId);
        }
    }

    /**
     * Create a new instance of a job class
     * @param int $jobId
     * @return object
     */
    private function getNewJobInstance(int $jobId): BrowserJob {
        $jobClass = Cache::get('jobClass' . $jobId);
        if ($jobClass == null) { // If we don't have the class in cache, we put all of the job in cache
            $this->indexJobsClassesById();
            return $this->jobInstancesByJobId[$jobId]; // indexJobsClassesById() already created an instance of the job
        }
        // If we have the class in cache, we create a new instance of it
        $instance = new $jobClass();
        $this->jobInstancesByJobId[$jobId] = $instance;
        return $instance;
    }

    /**
     * Terminate all jobs
     * @return void
     */
    public function terminateAll() {
        foreach ($this->jobInstancesByJobId as $jobInstance) {
            $jobInstance->terminate();
        }
    }
}
