<?php

namespace App\Modules\Workflow;

use App\Models\ValidationModel;
use App\Modules\Workflow\WorkflowEvent;

class WorkflowAction extends ValidationModel
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'workflow_actions';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = ['workflow_event_id', 'action', 'settings', 'condition'];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = ['template'];

    /**
     * Array of validation rules.
     *
     * @var array
     */
    protected static $rules = [
        'workflow_event_id' => ['required'],
        'action'            => ['required'],
    ];

    /**
     * Setter for the settings attribute. It automatically encodes the value passed
     * as a json array to be stored in the database.
     *
     * @param $value - an array that will be converted to JSON
     *
     * @return null
     */
    public function setSettingsAttribute($value)
    {
        $this->attributes['settings'] = json_encode($value);
    }

    /**
     * Getter for the settings attribute. It converts a JSON string fetched from the database
     * to an stdClass object.
     *
     * @return array
     */
    public function getSettingsAttribute()
    {
        return json_decode($this->attributes['settings'], true);
    }

    /**
     * Returns a list containing all the available actions.
     *
     * @return array
     */
    public static function getActions()
    {
        return [
            ['name' => 'Send Email', 'value' => 'App\Modules\Workflow\Actions\SendEmailAction', 'template' => 'workflow/actions/send_email.html'],
        ];
    }

    /**
     * The event linked to this action.
     *
     * @return App\Modules\Workflow\WorkflowEvent
     */
    public function workflow_event()
    {
        return $this->belongsTo(WorkflowEvent::class, 'workflow_event_id');
    }

    /**
     * Restrict query results to actions that should perform when the condition is satisfied.
     *
     * @return Illuminate\Support\Query
     */
    public function scopeCondition($query, $value = 1)
    {
        return $query->where('condition', $value);
    }

    /**
     * Retrieves the template id for this action.
     *
     * @return string
     */
    public function getTemplateAttribute()
    {
        foreach ($this->getActions() as $action) {
            if ($action['value'] == $this->action) {
                return $action['template'];
            }
        }

        return '';
    }

    /**
     * Fires the action.
     *
     * @param $data - the data that will get passed to the action class.
     *
     * @return null
     */
    public function fire($data)
    {
        // We are now creating the action object and pass it the orignal
        // data from the event
        $actionClass = $this->action;

        if (! class_exists($actionClass)) {
            throw new Exception('Requested class does not exist ('.$actionClass.')');
        }

        $action = new $actionClass($this, $this->workflow_event, $data);

        // The object should be ready, we will now fire it
        $action->fire();
    }
}
