<?php

namespace App\Modules\Push;

use Illuminate\Support\Facades\Log;
use Davibennun\LaravelPushNotification\Facades\PushNotification;

class EventObserver
{
    /**
     * Execute the workflow when the model gets created.
     *
     * @param  Eloquent $model
     *
     * @return void
     */
    public function created($model)
    {
        $this->fireEvent($model, 'created');
    }

    /**
     * Execute the workflow when the model gets updated.
     *
     * @param  Eloquent $model
     *
     * @return void
     */
    public function updated($model)
    {
        $this->fireEvent($model, 'updated');
    }

    /**
     * Execute the workflow when the model gets deleted.
     *
     * @param  Eloquent $model
     *
     * @return void
     */
    public function deleted($model)
    {
        $this->fireEvent($model, 'deleted');
    }

    /**
     * Triggers the send notification with a given event name.
     *
     * @param  string $event
     *
     * @return void
     */
    protected function fireEvent($model, $event = 'created')
    {
        if ($devices = $this->getDevices()) {
            $this->sendNotification($devices, $this->getMessage($model, $event));
        }
    }

    /**
     * Retrieves all the devices from the database.
     *
     * @return Sly\NotificationPusher\Collection\DeviceCollection
     */
    protected function getDevices()
    {
        $collection = PushNotification::DeviceCollection();
        $devices = PushDevice::query()->where('type', '!=', 'preview')->get();

        // We do not want to do anything if there are no devices in the database
        if ($devices->count() == 0) {
            return false;
        }

        foreach ($devices as $device) {
            $collection->add(PushNotification::Device($device->device_id));
        }

        return $collection;
    }

    /**
     * Generates the message for the push notification.
     *
     * @param  Eloquent $model
     * @param  string $event
     *
     * @return Sly\NotificationPusher\Model\Message
     */
    protected function getMessage($model, $event = 'created')
    {
        return PushNotification::Message('sync', [
                'custom' => [
                    'table'    => class_basename($model),
                    'action'   => $event,
                    'table_id' => $model->id,
                ],
            ]);
    }

    /**
     * Send the actual notification to a list of devices with a given message.
     *
     * @param  Sly\NotificationPusher\Collection\DeviceCollection $devices
     * @param  Sly\NotificationPusher\Model\Message $message
     *
     * @return void
     */
    protected function sendNotification($devices, $message)
    {
        try {
            $data = PushNotification::app('androidPlumbob')->to($devices)->send($message);

            // Here we will detect the obsolete devices ids that can now
            // be deleted. We can determine that based on the response we get from google.
            foreach ($data as $device) {
                $response = $device->getAdapter()->getResponse();

                // Check to see if the response exists
                if (! $response) {
                    continue;
                } // Skip to the next one in the list

                if ($response->getFailureCount() > 0 || $response->getCanonicalCount() > 0) {
                    $toRemove = array_merge($response->getResult($response::RESULT_ERROR), $response->getResult($response::RESULT_CANONICAL));

                    // log the items that are being removed
                    Log::info('Removing the following devices_ids from the push table');
                    Log::info($toRemove);

                    foreach ($toRemove as $deviceId => $status) {
                        PushDevice::query()->where('device_id', '=', $deviceId)->delete();
                    }
                }
            }
        } catch (Exception $e) {
            Log::error($e);
        }
    }
}
