<?php
/********************************************************************************
 * (c)1337 aheadware.com - All rights reserved
 ********************************************************************************/


class TB_Server_Core_Notification
{
    /**
     * @param $inAppLink
     * @return array
     */
    public static function createAdditionalData( $inAppLink, $forceReload = false )
    {
        $addData = array(
            'inAppUrl' => $inAppLink,
            'forceRelead' => $forceReload
        );
        return $addData;
    }

    /**
     * @param $headline
     * @param $message
     * @param $teamId
     * @param $additionalData
     */
    public static function sendToTeam( $headline, $message, $teamId, array $additionalData = NULL )
    {
        $profileIds = TB_Shared_Ent_TeamData_Profile::getProfilesByTeamId( $teamId );
        if ( 0 < count( $profileIds ) )
        {
            self::sendToProfiles( $headline, $message, $profileIds, $additionalData );
        }
    }

    /**
     * @param TB_Shared_Ent_TeamData_Appointment $appointment
     * @throws Exception
     */
    public static function notifyNewAppointmentChat( TB_Shared_Ent_TeamData_Appointment $appointment )
    {
        $profileIds = array();
        $attendees = TB_Shared_Ent_TeamData_Attendee::getAttendeesWithStatusForAppointmentId(
            $appointment->id,
            TB_Shared_Ent_TeamData_Attendee::STATUS_ACCEPTED
        );
        $attendeesWaiting = TB_Shared_Ent_TeamData_Attendee::getAttendeesWithStatusForAppointmentId(
            $appointment->id,
            TB_Shared_Ent_TeamData_Attendee::STATUS_WAITING
        );

        $adminProfiles = TB_Shared_Ent_TeamData_Profile::getAdminsOfTeamId( $appointment->team_id );
        $attendees = array_merge( $attendees, $attendeesWaiting );

        /** @var TB_Shared_Ent_TeamData_Attendee $attendee */
        foreach( $attendees as $attendee )
        {
            array_push( $profileIds, $attendee->profile_id );
        }

        /** @var TB_Shared_Ent_TeamData_Profile $adminProfile */
        foreach( $adminProfiles as $adminProfile )
        {
            if ( !in_array( $adminProfile->id, $profileIds ) )
            {
                array_push( $profileIds, $adminProfile->id );
            }
        }

        $headline = 'Neue Nachricht';
        $message = 'Terminchat: ' . $appointment->getName();
        $additionalData = self::createAdditionalData( '#/appointment/' . $appointment->id . '/chat' );
        self::sendToProfiles(
            $headline,
            $message,
            $profileIds,
            $additionalData,
            'appointment-' . $appointment->id
        );
    }

    /**
     * @param array $profileIds
     * @param TB_Shared_Ent_TeamData_Appointment $appointment
     * @param TB_Shared_Ent_TeamData_Team $team
     * @throws Exception
     */
    public static function notifyAppointmentStart( array $profileIds,
                                                   TB_Shared_Ent_TeamData_Appointment $appointment,
                                                   TB_Shared_Ent_TeamData_Team $team )
    {
        // Notify
        $headline = "Termin beginnt in Kürze";
        $message = "[" . $team->display_name . "] Der Termin " . $appointment->getName() . " fängt in Kürze an.";
        $additionalData = self::createAdditionalData( '#/appointment/' . $appointment->id );
        self::sendToProfiles(
            $headline,
            $message,
            $profileIds,
            $additionalData
        );
    }

    public static function notifyBirthday( array $profileIds, TB_Shared_Ent_TeamData_Profile $birthdayProfile )
    {
        $age = $birthdayProfile->getAge();

        if ( (int)$age <= 2 )
        {
            return;
        }

        $headline = $birthdayProfile->getName() . " hat heute Geburtstag.";
        $message = "Das Gruppenmitglied wird heute " . $age . " Jahre alt.";
        $additionalData = self::createAdditionalData( '#/profile/' . $birthdayProfile->id );
        self::sendToProfiles(
            $headline,
            $message,
            $profileIds,
            $additionalData
        );
    }

    /**
     * @param TB_Shared_Ent_TeamData_Team $team
     * @param TB_Shared_Ent_TeamData_Profile $profile
     */
    public static function notifyNewMemberJoined( TB_Shared_Ent_TeamData_Team $team,
                                                  TB_Shared_Ent_TeamData_Profile $profile )
    {
        // Get admins of team
        $profileIds = array();
        $adminsOfTeam = TB_Shared_Ent_TeamData_Profile::getAdminsOfTeamId( $team->id );
        /** @var TB_Shared_Ent_TeamData_Profile $admin */
        foreach( $adminsOfTeam as $admin )
        {
            array_push( $profileIds, $admin->id );
        }

        // Notify
        $headline = "Neues Mitglied";
        $message = "Ein neues Mitglied ist deiner Gruppe beigetreten.";
        $additionalData = self::createAdditionalData( '#/profile/' . $profile->id );
        self::sendToProfiles(
            $headline,
            $message,
            $profileIds,
            $additionalData
        );
    }

    /**
     * @param TB_Shared_Ent_TeamData_Profile $profile
     * @param TB_Shared_Ent_TeamData_Appointment $appointment
     */
    public static function notifyAttenddeeStatusChangeByAdmin( TB_Shared_Ent_TeamData_Attendee $attendee,
                                                               TB_Shared_Ent_TeamData_Appointment $appointment )
    {
        // Send notifications
        TB_Server_Core_Notification::sendToProfiles(
            'Admin Änderung',
            'Dein Zu-/Absagestatus wurde vom Admin beim Termin ' . $appointment->subject . ' geändert.',
            array( $attendee->profile_id ),
            TB_Server_Core_Notification::createAdditionalData( '#/appointment/' . $appointment->id )
        );

    }

    /**
     * @param array $profileIds
     * @param TB_Shared_Ent_TeamData_Appointment $appointment
     * @throws Exception
     */
    public static function notifyAppointmentCancellation( array $profileIds,
                                                          TB_Shared_Ent_TeamData_Appointment $appointment )
    {
        TB_Server_Core_Notification::sendToProfiles(
            'Termin abgesagt',
            'Achtung. Der Termin ' . $appointment->subject . ' wurde abgesagt.',
            $profileIds,
            TB_Server_Core_Notification::createAdditionalData( '#/appointment/' . $appointment->id )
        );
    }

    public static function notifyNewAppointment( TB_Shared_Ent_TeamData_Appointment $appointment, $isSerial = false )
    {
        $profileIds = array();
        $profileIdsAlreadyAdded = array();
        $members = TB_Shared_Ent_TeamData_Profile::getProfilesByTeamId( $appointment->team_id );
        $atts = TB_Shared_Ent_TeamData_Attendee::getAttendeesWithStatusForAppointmentId( $appointment->id, TB_Shared_Ent_TeamData_Attendee::STATUS_ACCEPTED );

        /** @var TB_Shared_Ent_TeamData_Profile $member */
        foreach( $members as $member )
        {
            // Exclude members who do not belong
            if ( false === $appointment->isVisibleByProfile( $member ) )
            {
                continue;
            }

            $onList = false;

            /** @var TB_Shared_Ent_TeamData_Attendee $att */
            foreach( $atts as $att )
            {
                if ( $member->id == $att->profile_id )
                {
                    $onList = true;
                    break;
                }
            }

            if ( true === $onList )
            {
                array_push( $profileIdsAlreadyAdded, $member->id );
            }
            else
            {
                array_push( $profileIds, $member->id );
            }
        }

        $appointment->start_dt->setTimezone( new \DateTimeZone( 'Europe/Berlin' ) );

        TB_Server_Core_Notification::sendToProfiles(
            $isSerial ? 'Neuer Serientermin' : 'Neuer Termin (Jetzt buchen)',
            $isSerial ? $appointment->subject : $appointment->subject . ' am ' . $appointment->start_dt->format( 'd.m.Y' ) . ' um ' . $appointment->start_dt->format( 'H:i' ) . ' Uhr',
            $profileIds,
            $isSerial ? TB_Server_Core_Notification::createAdditionalData( '#/home' ) : TB_Server_Core_Notification::createAdditionalData( '#/appointment/' . $appointment->id )
        );

        if ( 0 < count( $profileIdsAlreadyAdded ) )
        {
            TB_Server_Core_Notification::sendToProfiles(
                $isSerial ? 'Neuer Serientermin (Dein Platz ist reserviert)' : 'Neuer Termin (Dein Platz ist reserviert)',
                $isSerial ? $appointment->subject : $appointment->subject . ' am ' . $appointment->start_dt->format( 'd.m.Y' ) . ' um ' . $appointment->start_dt->format( 'H:i' ) . ' Uhr',
                $profileIdsAlreadyAdded,
                $isSerial ? TB_Server_Core_Notification::createAdditionalData( '#/home' ) : TB_Server_Core_Notification::createAdditionalData( '#/appointment/' . $appointment->id )
            );
        }

    }

    /**
     * @param TB_Shared_Ent_TeamData_Profile $profile
     * @param TB_Shared_Ent_TeamData_Team $group
     * @param $newRole
     * @throws Exception
     */
    public static function notifyNewRole( TB_Shared_Ent_TeamData_Profile $profile,
                                          TB_Shared_Ent_TeamData_Team $group,
                                          $newRole )
    {
        $profileIds = array( $profile->id );
        $msg = 'Deine Rolle im Team ' . $group->display_name . ' wurde auf ' . ( ( $newRole === TB_Shared_Ent_TeamData_Profile::ROLE_COTRAINER ) ? 'Admin' : 'Mitglied' ) . ' gesetzt.';
        TB_Server_Core_Notification::sendToProfiles(
            'Neue Rolle',
            $msg,
            $profileIds,
            TB_Server_Core_Notification::createAdditionalData( '#/group/members' . $group->id, true )
        );
    }

    /**
     * @param TB_Shared_Ent_TeamData_Profile $profile
     * @param TB_Shared_Ent_TeamData_Team $group
     */
    public static function notifyTeamLeave( TB_Shared_Ent_TeamData_Profile $profile,
                                            TB_Shared_Ent_TeamData_Team $group )
    {
        $profileIds = array( $profile->id );
        $msg = 'Du wurdest aus dem Team ' . $group->display_name . ' entfernt.';
        TB_Server_Core_Notification::sendToProfiles(
            'Entfernt',
            $msg,
            $profileIds,
            TB_Server_Core_Notification::createAdditionalData( '#/groups', true )
        );
    }

    /**
     * @param $headline
     * @param $message
     * @param array $profileIds
     * @param array|NULL $additionalData
     * @param string|NULL $refId
     */
    public static function sendToProfiles(
        $headline,
        $message,
        array $profileIds,
        array $additionalData = NULL,
        $refId = NULL,
        TB_Shared_Ent_TeamData_Profile $creator = NULL )
    {
        if ( is_null( $headline ) && is_null( $message ) )
        {
            throw new \Exception( 'Notification creation failed. Headline AND message are null.' );
        }

        if ( is_null( $creator ) && TB_Server_Core_Session::get()->isInitialized() )
        {
            $creator = TB_Server_Core_Session::get()->getProfile();
        }

        // start: Create notification entities for DB
        $dtNow = TB_Server_Utils_Helper::getUTCNowDateTime();
        $entNotification = new TB_Shared_Ent_TeamData_Notification();
        $entNotification->ref_id = $refId;
        $entNotification->headline = _xss( $headline );
        $entNotification->message = _xss( $message );
        $entNotification->creator_profile_id = is_null( $creator ) ? NULL : $creator->id;
        $entNotification->creator_name = is_null( $creator ) ? NULL : $creator->getName();
        $entNotification->additional_data_js = $additionalData;
        $entNotification->is_read = 0;
        $entNotification->last_updated_dt = $dtNow;
        $entNotification->created_dt = $dtNow;

        foreach( $profileIds as $profileId )
        {
            /*
             * DISABLED FOR NOW - SINCE IT SEEMS TO CAUSE ERRORS
             *
            if ( !is_null( $refId ) )
            {
                // If profileId already has a notification about this event
                if ( TB_Shared_Ent_TeamData_Notification::hasProfileIdUnreadOfRefId( $profileId, $refId ) )
                {
                    // Skip creation of another notificationb
                    continue;
                }
            }
            */
            $entNotification->id = NULL;
            $entNotification->receiver_profile_id = $profileId;
            $entNotification->save();
        }
        // stop: Create notification entities for DB

        // start: Push Notificatins
        TB_Server_Core_OneSignal::sendToProfiles( $headline, $message, $profileIds, $additionalData );
        // stop : Push Notificatins
    }
}