<?php

namespace App\Jobs;

use App\Feedback;
use App\Mark;
use App\Wowa;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use RUCD\Training\SolutionDistance;
use RUCD\Training\Trainer;
use RUCD\Training\TrainerParameters;

class WowaJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $feedbacks;
    protected $wowa;

    /**
     * Create a new job instance.
     *
     * @param Wowa $wowa
     */
    public function __construct(Wowa $wowa)
    {
        $this->wowa = $wowa;
        $this->feedbacks = Feedback::all();
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $memory = memory_get_usage();
        $i = 1;
        $logger = new Logger('wowa-training-test');
        $logger->pushHandler(new StreamHandler(__DIR__.'/app.log', Logger::DEBUG));
        $logger->debug("Job Beginning");
        $this->wowa->status = Wowa::STATE_RUNNING;
        $this->wowa->start_time = time();
        $this->wowa->save();
        if (count($this->feedbacks) == 0) {
            $this->wowa->status = Wowa::STATE_FAILED;
            $this->wowa->end_time = time();
            $this->wowa->save();
            return;
        }
        $logger->debug("Begin find all related evidences");
        $evidences = [];
        $is_true_alert = [];
        foreach ($this->feedbacks as $feedback) {
            $logger->debug("Memory usage : " . (memory_get_usage() - $memory));
            $logger->debug("Feedback number : " . $i);
            $i++;
            $evidence_references = $feedback->report()->references;
            $logger->debug("Var Dump references : " . var_dump($evidence_references));
            $is_true_alert[] = $feedback->is_true_alert;
            $scores_references = [];
            foreach ($evidence_references as $evidence_reference) {
                $scores_references[] = Mark::get()->findEvidenceById($evidence_reference)->score;
                $logger->debug("Var dump scores evidences : " . var_dump($scores_references));
            }
            $evidences[] = $scores_references;
        }
        $logger->debug("End find all related evidences");
        $training_prameters = new TrainerParameters(
            $logger,
            $this->wowa->population,
            $this->wowa->crossover_rate,
            $this->wowa->mutation_rate,
            TrainerParameters::SELECTION_METHOD_RWS,
            $this->wowa->generation_number,
            TrainerParameters::INITIAL_POPULATION_GENERATION_RANDOM
        );
        $trainer = new Trainer($training_prameters, new SolutionDistance(count($evidences[0])));
        $solution = $trainer->run($evidences, $is_true_alert);
        //var_dump($solution);
        $this->wowa->status = Wowa::STATE_SUCCESS;
        $this->wowa->w_weights = $solution->weights_w;
        $this->wowa->p_weights = $solution->weights_p;
        $this->wowa->score = $solution->distance;
        $this->wowa->end_time = time();
        $this->wowa->save();
    }
}