<?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;
use Barryvdh\Debugbar\Facade;

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

    protected $feedback_number;
    protected $wowa;
    protected $is_true_alert = [];
    protected $evidences = [];

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

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        $logger = new Logger('wowa-training-test');
        $logger->pushHandler(new StreamHandler(__DIR__.'/app.log', Logger::DEBUG));
        $this->wowa->status = Wowa::STATE_RUNNING;
        $this->wowa->start_time = time();
        $this->wowa->save();
        if ($this->feedback_number == 0) {
            $this->wowa->status = Wowa::STATE_FAILED;
            $this->wowa->end_time = time();
            $this->wowa->save();
            return;
        }
        $logger->debug("Begin find all related evidences");
        Feedback::chunk(100, function ($feedbacks) {
            foreach ($feedbacks as $feed) {
                $evidence_references = $feed->report()->references;
                $this->is_true_alert[] = $feed->is_true_alert;
                $scores_references = [];
                foreach ($evidence_references as $evidence_reference) {
                    $scores_references[] = Mark::get()->findEvidenceById($evidence_reference)->score;
                }
                $this->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($this->evidences[0])));
        $solution = $trainer->run($this->evidences, $this->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();
    }
}