<?php

/* For licensing terms, see /license.txt */

use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CoreBundle\Entity\User;
use Chamilo\CoreBundle\Enums\ActionIcon;

/**
 * Config setting:
 * $_configuration['allow_scheduled_announcements'] = true;.
 *
 * Setup linux cron file:
 * main/cron/scheduled_announcement.php
 */
class ScheduledAnnouncement extends Model
{
    public $table;
    public $columns = ['id', 'subject', 'message', 'date', 'sent', 'session_id'];

    /**
     * Constructor.
     */
    public function __construct()
    {
        parent::__construct();
        $this->table = 'scheduled_announcements';
    }

    public function get_all(array $options = []): array
    {
        return Database::select(
            '*',
            $this->table,
            ['where' => $options, 'order' => 'subject ASC']
        );
    }

    /**
     * @return mixed
     */
    public function get_count()
    {
        $row = Database::select(
            'count(*) as count',
            $this->table,
            [],
            'first'
        );

        return $row['count'];
    }

    /**
     * Displays the title + grid.
     *
     * @param int $sessionId
     *
     * @return string
     */
    public function getGrid($sessionId)
    {
        // action links
        $action = '<div class="actions" style="margin-bottom:20px">';
        $action .= Display::url(
            Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back')),
            api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$sessionId
        );

        $action .= '<a href="'.api_get_self().'?action=add&session_id='.$sessionId.'">'.
            Display::getMdiIcon(ActionIcon::ADD, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Add')).'</a>';
        $action .= '<a href="scheduled_announcement.php?action=run&session_id='.$sessionId.'">'.
            Display::getMdiIcon(ActionIcon::SEND_MESSAGE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Send pending announcements manually')).
            '</a>';

        $action .= '</div>';

        $html = $action;
        $html .= '<div id="session-table" class="table-responsive">';
        $html .= Display::grid_html('programmed');
        $html .= '</div>';

        return $html;
    }

    /**
     * Returns a Form validator Obj.
     *
     * @param int    $id
     * @param string $url
     * @param string $action      add, edit
     * @param array  $sessionInfo
     *
     * @return FormValidator form validator obj
     */
    public function returnSimpleForm($id, $url, $action, $sessionInfo = [])
    {
        $form = new FormValidator(
            'announcement',
            'post',
            $url
        );

        $form->addHidden('session_id', $sessionInfo['id']);
        $form->addDateTimePicker('date', get_lang('Date'));
        $form->addText('subject', get_lang('Subject'));
        $form->addHtmlEditor('message', get_lang('Message'));

        $extraField = new ExtraField('scheduled_announcement');
        $extra = $extraField->addElements($form, $id);
        $js = $extra['jquery_ready_content'];
        $form->addHtml("<script> $(function() { $js }); </script> ");

        $this->setTagsInForm($form);

        $form->addCheckBox('sent', null, get_lang('Message Sent'));

        if ('edit' === $action) {
            $form->addButtonUpdate(get_lang('Edit'));
        }

        return $form;
    }

    /**
     * Returns a Form validator Obj.
     *
     * @todo the form should be auto generated
     *
     * @param string $url
     * @param string $action add, edit
     * @param array
     *
     * @return FormValidator form validator obj
     */
    public function returnForm($url, $action, $sessionInfo = [])
    {
        // Setting the form elements
        $header = get_lang('Add');

        if ('edit' === $action) {
            $header = get_lang('Edit');
        }

        $form = new FormValidator(
            'announcement',
            'post',
            $url
        );

        $form->addHeader($header);
        if ('add' === $action) {
            $form->addHtml(
                Display::return_message(
                    nl2br(
                        get_lang(
                            'This form allows scheduling announcements to be sent automatically to the students who are taking a course in a session.'
                        )
                    ),
                    'normal',
                    false
                )
            );
        }
        $form->addHidden('session_id', $sessionInfo['id']);

        $useBaseDate = false;
        $startDate = $sessionInfo['access_start_date'];
        $endDate = $sessionInfo['access_end_date'];

        if (!empty($startDate) || !empty($endDate)) {
            $useBaseDate = true;
        }

        $typeOptions = [
            'specific_date' => get_lang('Specific dispatch date'),
        ];

        if ($useBaseDate) {
            $typeOptions['base_date'] = get_lang("Dispatch based on the session's start/end dates");
        }

        $form->addSelect(
            'type',
            get_lang('Type'),
            $typeOptions,
            [
                'onchange' => "javascript:
                    if (this.options[this.selectedIndex].value == 'base_date') {
                        document.getElementById('options').style.display = 'block';
                        document.getElementById('specific_date').style.display = 'none';
                    } else {
                        document.getElementById('options').style.display = 'none';
                        document.getElementById('specific_date').style.display = 'block';
                    }
            ", ]
        );

        $form->addHtml('<div id="specific_date">');
        $form->addDateTimePicker('date', get_lang('Date'));
        $form->addHtml('</div>');
        $form->addHtml('<div id="options" style="display:none">');

        $startDate = $sessionInfo['access_start_date'];
        $endDate = $sessionInfo['access_end_date'];

        $form->addText(
            'days',
            get_lang('days'),
            false
        );

        $form->addSelect(
            'moment_type',
            get_lang('After or before'),
            [
                'after' => get_lang('After'),
                'before' => get_lang('Before'),
            ]
        );

        if (!empty($startDate)) {
            $options['start_date'] = get_lang('Start Date').' - '.$startDate;
        }

        if (!empty($endDate)) {
            $options['end_date'] = get_lang('End Date').' - '.$endDate;
        }
        if (!empty($options)) {
            $form->addSelect('base_date', get_lang('Dispatch based on the session\'s start/end dates'), $options);
        }

        $form->addHtml('</div>');
        $form->addText('subject', get_lang('Subject'));
        $form->addHtmlEditor('message', get_lang('Message'));

        $extraField = new ExtraField('scheduled_announcement');
        $extra = $extraField->addElements($form);
        $js = $extra['jquery_ready_content'];
        $form->addHtml("<script> $(function() { $js }); </script> ");
        $this->setTagsInForm($form);

        if ('edit' === $action) {
            $form->addButtonUpdate(get_lang('Edit'));
        } else {
            $form->addButtonCreate(get_lang('Add'));
        }

        return $form;
    }

    /**
     * @param int $id
     *
     * @return string
     */
    public function getAttachmentToString($id)
    {
        $file = $this->getAttachment($id);
        if (!empty($file) && !empty($file['value'])) {
            $url = $file['url'];

            return get_lang('Attachment').': '.Display::url(basename($file['url']), $url, ['target' => '_blank']);
        }

        return '';
    }

    /**
     * @param int $id
     *
     * @return array
     */
    public function getAttachment($id)
    {
        $extraFieldValue = new ExtraFieldValue('scheduled_announcement');

        return $extraFieldValue->get_values_by_handler_and_field_variable($id, 'attachment');
    }

    /**
     * @param int $urlId
     *
     * @return int
     */
    public function sendPendingMessages($urlId = 0)
    {
        if (!$this->allowed()) {
            return 0;
        }

        $messagesSent = 0;
        $now = api_get_utc_datetime();
        $result = $this->get_all();
        $extraFieldValue = new ExtraFieldValue('scheduled_announcement');

        foreach ($result as $result) {
            if (empty($result['sent'])) {
                if (!empty($result['date']) && $result['date'] < $now) {
                    $sessionId = $result['session_id'];
                    $sessionInfo = api_get_session_info($sessionId);
                    $session = api_get_session_entity($sessionId);
                    if (empty($sessionInfo)) {
                        continue;
                    }
                    $users = SessionManager::get_users_by_session(
                        $sessionId,
                        Session::STUDENT,
                        false,
                        $urlId
                    );
                    $generalCoaches = $session->getGeneralCoaches();

                    if (empty($users) || 0 === $generalCoaches->count()) {
                        continue;
                    }

                    $coachId = $generalCoaches->first()->getId();

                    $coachList = [];
                    if ($users) {
                        $sendToCoaches = $extraFieldValue->get_values_by_handler_and_field_variable(
                            $result['id'],
                            'send_to_coaches'
                        );
                        $courseList = SessionManager::getCoursesInSession($sessionId);
                        if (!empty($sendToCoaches) && !empty($sendToCoaches['value']) && 1 == $sendToCoaches['value']) {
                            foreach ($courseList as $courseItemId) {
                                $coaches = SessionManager::getCoachesByCourseSession(
                                    $sessionId,
                                    $courseItemId
                                );
                                $coachList = array_merge($coachList, $coaches);
                            }
                            $coachList = array_unique($coachList);
                        }

                        $this->update(['id' => $result['id'], 'sent' => 1]);
                        $attachments = $this->getAttachmentToString($result['id']);
                        $subject = $result['subject'];

                        $courseInfo = [];
                        if (!empty($courseList)) {
                            $courseId = current($courseList);
                            $courseInfo = api_get_course_info_by_id($courseId);
                        }

                        $message = '';
                        foreach ($users as $user) {
                            // Take original message
                            $message = $result['message'];
                            $userInfo = api_get_user_info($user['user_id']);

                            $progress = '';
                            if (!empty($sessionInfo) && !empty($courseInfo)) {
                                $progress = Tracking::get_avg_student_progress(
                                    $user['user_id'],
                                    api_get_course_entity($courseInfo['real_id']),
                                    [],
                                    api_get_session_entity($sessionId)
                                );
                            }

                            if (is_numeric($progress)) {
                                $progress = $progress.'%';
                            } else {
                                $progress = '0%';
                            }

                            $startTime = api_get_local_time(
                                $sessionInfo['access_start_date'],
                                null,
                                null,
                                true
                            );
                            $endTime = api_get_local_time(
                                $sessionInfo['access_end_date'],
                                null,
                                null,
                                true
                            );

                            $generalCoachName = [];
                            $generalCoachEmail = [];
                            /** @var User $generalCoach */
                            foreach ($generalCoaches as $generalCoach) {
                                $generalCoachName[] = $generalCoach->getFullName();
                                $generalCoachEmail[] = $generalCoach->getEmail();
                            }

                            $tags = [
                                '((session_name))' => $sessionInfo['name'],
                                '((session_start_date))' => $startTime,
                                '((general_coach))' => implode(' - ', $generalCoachName),
                                '((general_coach_email))' => implode(' - ', $generalCoachEmail),
                                '((session_end_date))' => $endTime,
                                '((user_complete_name))' => $userInfo['complete_name'],
                                '((user_firstname))' => $userInfo['firstname'],
                                '((user_lastname))' => $userInfo['lastname'],
                                '((user_first_name))' => $userInfo['firstname'],
                                '((user_last_name))' => $userInfo['lastname'],
                                '((lp_progress))' => $progress,
                            ];

                            $message = str_replace(array_keys($tags), $tags, $message);
                            $message .= $attachments;

                            MessageManager::send_message_simple(
                                $userInfo['user_id'],
                                $subject,
                                $message,
                                $coachId
                            );
                        }

                        $message = get_lang('You\'re receiving a copy because, you\'re a course coach').
                            '<br /><br />'.$message;

                        foreach ($coachList as $courseCoachId) {
                            MessageManager::send_message_simple(
                                $courseCoachId,
                                get_lang('You\'re receiving a copy because, you\'re a course coach').'&nbsp;'.$subject,
                                $message,
                                $coachId
                            );
                        }
                    }
                    $messagesSent++;
                }
            }
        }

        return $messagesSent;
    }

    /**
     * @return array
     */
    public function getTags()
    {
        return [
            '((session_name))',
            '((session_start_date))',
            '((session_end_date))',
            '((general_coach))',
            '((general_coach_email))',
            '((user_complete_name))',
            '((user_first_name))',
            '((user_last_name))',
            '((lp_progress))',
        ];
    }

    /**
     * @return bool
     */
    public function allowed()
    {
        return ('true' === api_get_setting('announcement.allow_scheduled_announcements'));
    }

    private function setTagsInForm(FormValidator $form)
    {
        $form->addLabel(
            get_lang('Tags'),
            Display::return_message(
                implode('<br />', $this->getTags()),
                'normal',
                false
            )
        );
    }
}
