<?php

namespace App\Modules\Bookings;

use Illuminate\Support\Facades\Log;
use App\Modules\Ews\Ews;
use Illuminate\Events\Dispatcher as Event;
use Exception;
use App\Facades\DBconfig;

class CalendarEventService
{
    /**
     * A reference to the Exchange Web Services.
     */
    private $ews;

    /**
     * A reference to the log writer.
     */
    private $log;

    /**
     * A reference to the event handler.
     */
    private $event;

    /**
     * A reference to the task object.
     *
     * @var App\Modules\Bookings\Task
     */
    protected $task;

    /**
     * Constructor function, where the dependency injection magic happens.
     *
     * @param \App\Modules\Ews\Ews				$ews
     * @param \Illuminte\Log\Writer 			$log
     * @param \Illuminate\Events\Dispatcher 	$event
     */
    public function __construct(Ews $ews, Log $log, Event $event)
    {
        $this->ews = $ews;
        $this->log = $log;
        $this->event = $event;
    }

    /**
     * Create a new calendar entry.
     *
     * @param  App\Modules\Bookings\Task $task
     *
     * @return string | false
     */
    public function create($task)
    {
        try {
            $this->setTask($task);

            // Check to see if the calendar module is enabled
            if (! DBconfig::get('ews::config.enabled')) {
                return false;
            }

            // We are wrapping the call in a try / catch
            // so even if Exchange is down the task will still be created
            // and the user will not have to suffer
            $response = $this->ews->createEvent($this->getTitle(), $task->onsite_start, $task->onsite_end, $this->getBody(), $this->getUsername(), $this->getUserEmail());

            // Check the response to see if it was successfull
            // and return the exchange id
            if ($response->ResponseMessages->CreateItemResponseMessage->ResponseClass == 'Success') {
                $this->event->fire('exchange.calendar.created', $response->ResponseMessages->CreateItemResponseMessage);

                return $response->ResponseMessages->CreateItemResponseMessage->Items->CalendarItem->ItemId->Id;
            }
        } catch (Exception $e) {
            $this->log->error($e);
        }

        return false;
    }

    /**
     * Update an existing calendar entry.
     *
     * @param  App\Modules\Bookings\Task $task
     *
     * @return void
     */
    public function update($task)
    {
        try {
            $this->setTask($task);

            // Check to see if the calendar module is enabled
            if (! DBconfig::get('ews::config.enabled')) {
                return false;
            }

            $item = \Ews::getItem($task->exchange_id);
            $email = $task->user ? $task->user->email : '';
            if ($item) {
                \Ews::updateEvent($item->ItemId->Id, $item->ItemId->ChangeKey, $task->onsite_start, $task->onsite_end, $email, $this->getTitle());
            }
        } catch (Exception $e) {
            $this->log->error($e);
        }
    }

    /**
     * Sets the task.
     *
     * @param \App\Modules\Bookings\Task $task
     */
    public function setTask($task)
    {
        $this->task = $task;

        return $this;
    }

    /**
     * Gets the task.
     *
     * @return \App\Modules\Bookings\Task
     */
    public function getTask()
    {
        return $this->task;
    }

    /**
     * Gets the title of the event.
     *
     * @return string
     */
    public function getTitle()
    {
        try {
            return  $this->task->user
                    ? $this->task->user->name.' to '.$this->getCustomerName().' ('.$this->task->title.')'
                    : $this->task->title;
        } catch (Exception $e) {
            $this->log->error($e);
        }
    }

    /**
     * Gets the body of the event.
     *
     * @return string
     */
    public function getBody()
    {
        try {
            return $this->task->problem.$this->getAdditionalInfo();
        } catch (Exception $e) {
            $this->log->error($e);
        }
    }

    /**
     * Get the assigned user's username.
     *
     * @return string
     */
    public function getUsername()
    {
        try {
            return $this->task->user->username;
        } catch (Exception $e) {
            $this->log->error($e);
        }
    }

    /**
     * Get the assigned user's email.
     *
     * @return string
     */
    public function getUserEmail()
    {
        try {
            return $this->task->user->email;
        } catch (Exception $e) {
            $this->log->error($e);
        }
    }

    /**
     * Gets additional information.
     *
     * @return string
     */
    public function getAdditionalInfo()
    {
        return  '<br /><br /><br />'.
                '----- Automatically appended details ----- <br />'.
                '<strong>Customer name:</strong> '.$this->getCustomerName().'<br />'.
                '<strong>Telephone:</strong> '.$this->getTelephone().'<br />'.
                '<strong>Address:</strong> '.$this->getAddress().'<br />'.
                '<strong>Booked in by:</strong> '.$this->task->creator->name;
    }

    /**
     * Get the name of the customer.
     *
     * @return string
     */
    public function getCustomerName()
    {
        return $this->task->client->name;
    }

    /**
     * Get all the customer telephone numbers.
     *
     * @return string
     */
    public function getTelephone()
    {
        if ($this->task->client_type == 'client') {
            return $this->task->site->primary_phone;
        }

        // Telephones for a customer
        $telephones = [];
        $client = $this->task->client;
        if ($client->phone) {
            $telephones[] = $client->phone;
        }
        if ($client->phone2) {
            $telephones[] = $client->phone2;
        }
        if ($client->mobile) {
            $telephones[] = $client->mobile;
        }

        return implode(', ', $telephones);
    }

    /**
     * Get the full address in an inline string.
     *
     * @return string
     */
    public function getAddress()
    {
        $addresses = [];

        if ($this->task->client_type == 'client') {
            $site = $this->task->site;

            if ($site->address) {
                $addresses[] = $site->address;
            }
            if ($site->address2) {
                $addresses[] = $site->address2;
            }
            if ($site->postcode) {
                $addresses[] = $site->postcode;
            }

            return implode(', ', $addresses);
        }

        // If this is not a business then it is a regular customer
        $client = $this->task->client;

        if ($client->address) {
            $addresses[] = $client->address;
        }
        if ($client->address2) {
            $addresses[] = $client->address2;
        }
        if ($client->town) {
            $addresses[] = $client->town;
        }
        if ($client->county) {
            $addresses[] = $client->county;
        }
        if ($client->postcode) {
            $addresses[] = $client->postcode;
        }

        return implode(', ', $addresses);
    }
}
