/**
 *	Provide the list of possible notification recipients.
 *
 *	@since 2.0
*/
function shd_ajax_notify()
{
    global $txt, $context, $smcFunc, $user_profile, $modSettings, $sourcedir;
    $session_check = checkSession('get', '', false);
    // check the session but don't die fatally.
    if (!empty($session_check)) {
        return $context['ajax_return'] = array('error' => $txt[$session_check]);
    }
    shd_load_language('sd_language/SimpleDeskNotifications');
    require_once $sourcedir . '/sd_source/SimpleDesk-Notifications.php';
    if (!empty($context['ticket_id'])) {
        $query = shd_db_query('', '
			SELECT hdt.private, hdt.id_member_started, id_member_assigned, id_dept, status
			FROM {db_prefix}helpdesk_tickets AS hdt
			WHERE {query_see_ticket}
				AND hdt.id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
        if ($smcFunc['db_num_rows']($query) != 0) {
            $ticket = $smcFunc['db_fetch_assoc']($query);
        }
        $smcFunc['db_free_result']($query);
    }
    if (empty($ticket) || !shd_allowed_to('shd_singleton_email', $ticket['id_dept']) || $ticket['status'] == TICKET_STATUS_CLOSED || $ticket['status'] == TICKET_STATUS_DELETED) {
        return $context['ajax_return'] = array('error' => $txt['shd_no_ticket']);
    }
    // So, we need to start figuring out who's going to be notified, who won't be and who we might be interested in notifying.
    $notify_list = array('being_notified' => array(), 'optional' => array(), 'optional_butoff' => array());
    // Let's get all the possible actual people. The possible people who can be notified... well, they're staff.
    $staff = shd_get_visible_list($ticket['id_dept'], $ticket['private'], $ticket['id_member_started'], empty($modSettings['shd_admins_not_assignable']), false);
    // Let's start figuring it out then! First, get the big ol' lists.
    $query = $smcFunc['db_query']('', '
		SELECT id_member, notify_state
		FROM {db_prefix}helpdesk_notify_override
		WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        $notify_list[$row['notify_state'] == NOTIFY_NEVER ? 'optional_butoff' : 'being_notified'][$row['id_member']] = true;
    }
    // Did we exclude admins? If we did, we would have scooped the list of admins. If they're in the 'not being notified but you can...' list, remove them.
    if (!empty($context['list_admin_exclude'])) {
        foreach ($context['list_admin_exclude'] as $user_id) {
            if (isset($notify_list['optional_butoff'][$user_id])) {
                unset($notify_list['optional_butoff'][$user_id]);
            }
        }
    }
    // Now we get the list by preferences. This is where it starts to get complicated.
    $possible_members = array();
    // People who want replies to their own ticket, without including the ticket starter because they'd know about it...
    if (!empty($modSettings['shd_notify_new_reply_own']) && $context['user']['id'] != $ticket['id_member_started']) {
        $possible_members[$ticket['id_member_started']]['new_reply_own'] = true;
    }
    // The ticket is assigned to someone and they want to be notified if it changes.
    if (!empty($modSettings['shd_notify_new_reply_assigned']) && !empty($ticket['id_member_assigned']) && $context['user']['id'] != $ticket['id_member_assigned']) {
        $possible_members[$ticket['id_member_assigned']]['new_reply_assigned'] = true;
    }
    // So, if you're staff, and you've replied to this ticket before, do you want to be notified this time?
    if (!empty($modSettings['shd_notify_new_reply_previous'])) {
        $query = $smcFunc['db_query']('', '
			SELECT id_member
			FROM {db_prefix}helpdesk_ticket_replies
			WHERE id_ticket = {int:ticket}
			GROUP BY id_member', array('ticket' => $context['ticket_id']));
        $responders = array();
        while ($row = $smcFunc['db_fetch_row']($query)) {
            $responders[] = $row[0];
        }
        // this shouldn't be nil, ever, because we're replying, so the topic already exists so there's at least one name in there...
        $smcFunc['db_free_result']($query);
        $responders = array_intersect($responders, $staff);
        foreach ($responders as $id) {
            $possible_members[$id]['new_reply_previous'] = true;
        }
    }
    // If you're staff, did you have 'spam my inbox every single time' selected?
    if (!empty($modSettings['shd_notify_new_reply_any'])) {
        foreach ($staff as $id) {
            $possible_members[$id]['new_reply_any'] = true;
        }
    }
    // Now we have the list of possibles, exclude everyone who is either set to on, or off, since we don't need to query those for preferences.
    foreach ($possible_members as $id => $type_list) {
        if (isset($notify_list['being_notified'][$id]) || isset($notify_list['optional_butoff'][$id])) {
            unset($possible_members[$id]);
        }
    }
    if (!empty($possible_members)) {
        // Get the default preferences
        $prefs = shd_load_user_prefs(false);
        $pref_groups = $prefs['groups'];
        $base_prefs = $prefs['prefs'];
        // Build a list of users -> default prefs. We know this is for the list of possible contenders only.
        $member_prefs = array();
        $pref_list = array();
        foreach ($possible_members as $id => $type_list) {
            foreach ($type_list as $type => $value) {
                $member_prefs[$id][$type] = $base_prefs['notify_' . $type]['default'];
                $pref_list['notify_' . $type] = true;
            }
        }
        // Grab pref list from DB for these users and update
        $query = $smcFunc['db_query']('', '
			SELECT id_member, variable, value
			FROM {db_prefix}helpdesk_preferences
			WHERE id_member IN ({array_int:members})
				AND variable IN ({array_string:variables})', array('members' => array_keys($possible_members), 'variables' => array_keys($pref_list)));
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $row['id_member'] = (int) $row['id_member'];
            $variable = substr($row['variable'], 7);
            if (isset($member_prefs[$row['id_member']][$variable])) {
                $member_prefs[$row['id_member']][$variable] = $row['value'];
            }
        }
        $smcFunc['db_free_result']($query);
        // unset $members where member pref doesn't indicate they want it on.
        foreach ($member_prefs as $id => $value) {
            foreach ($value as $pref_id => $pref_item) {
                if (empty($pref_item)) {
                    unset($possible_members[$id][$pref_id]);
                }
            }
        }
        // Now, it's possible that we have a ticket that the starter can't see, but that their preferences would indicate they'd like a reply.
        // What should be done here is to remove them from the automatic list, and make them part of the ping list instead.
        if (!empty($ticket['id_member_started']) && !in_array($ticket['id_member_started'], $staff)) {
            $possible_members[$ticket['id_member_started']] = array();
        }
        // Now the clever bit, we've taken everyone who wasn't on the normal notify list, and figured out what their preferences are.
        // We now traverse $possible_members by id, if the array is empty, we know none of their preferences accounted for emails - so they're possible.
        // Otherwise we add them to the list of being notified.
        foreach ($possible_members as $id => $list) {
            if (empty($list)) {
                $notify_list['optional'][$id] = true;
            } else {
                $notify_list['being_notified'][$id] = true;
            }
        }
    }
    // By now we have three lists that include people who will be notified, people who could be notified, and people who don't really want to be.
    // Let's translate that into a list of people that we can make use of.
    $members = array_merge(array_keys($notify_list['being_notified']), array_keys($notify_list['optional']), array_keys($notify_list['optional_butoff']));
    if (!empty($members)) {
        // Get everyone's name.
        $loaded = loadMemberData($members);
        foreach ($loaded as $user) {
            if (!empty($user_profile[$user]) && $user_profile[$user]['is_activated'] > 0 && $user_profile[$user]['is_activated'] < 10) {
                // active & not banned
                $people[$user] = array('id' => $user, 'name' => $user_profile[$user]['real_name']);
            }
        }
        // Right, now let's step through and tidy up the three lists
        foreach ($notify_list as $list_type => $list_members) {
            foreach ($list_members as $id_member => $data) {
                if (isset($people[$id_member]) && $id_member != $context['user']['id']) {
                    // We really shouldn't be in this list.
                    $list_members[$id_member] = $people[$id_member]['name'];
                } else {
                    unset($list_members[$id_member]);
                }
            }
            if (!empty($list_members)) {
                asort($list_members);
                array_walk($list_members, 'shd_format_notify_name', $ticket['id_member_started']);
                $notify_list[$list_type] = $list_members;
            } else {
                unset($notify_list[$list_type]);
            }
        }
    }
    if (empty($notify_list) || empty($members)) {
        return $context['ajax_raw'] = '<notify><![C' . 'DATA[' . cleanXml($txt['shd_ping_none']) . ']' . ']></notify>';
    } else {
        ob_start();
        echo '<notify><![C', 'DATA[';
        $selected = array();
        if (!empty($_GET['list'])) {
            $_GET['list'] = explode(',', $_GET['list']);
            foreach ($_GET['list'] as $id) {
                if ((int) $id > 0) {
                    $selected[] = (int) $id;
                }
            }
        }
        if (!empty($notify_list['being_notified'])) {
            echo '<span class="shd_ajax_head">', $txt['shd_ping_already_' . (count($notify_list['being_notified']) == 1 ? '1' : 'n')], '</span><br />', implode(', ', $notify_list['being_notified']);
        }
        if (!empty($notify_list['optional'])) {
            if (!empty($notify_list['being_notified'])) {
                echo '<br /><br />';
            }
            echo '<span class="shd_ajax_head">', $txt['shd_ping_' . (count($notify_list['optional']) == 1 ? '1' : 'n')], '</span><br />';
            foreach ($notify_list['optional'] as $id => $member) {
                echo '<div class="shd_ajaxnotify"><input type="checkbox" name="notify[', $id, ']" value="', $id, '"', in_array($id, $selected) ? ' checked="checked"' : '', ' class="input_check" /> ', $member, '</div>';
            }
        }
        if (!empty($notify_list['optional_butoff'])) {
            if (!empty($notify_list['being_notified']) || !empty($notify_list['optional_butoff'])) {
                echo '<br /><br />';
            }
            echo '<span class="shd_ajax_head">', $txt['shd_ping_none_' . (count($notify_list['optional_butoff']) == 1 ? '1' : 'n')], '</span><br />';
            foreach ($notify_list['optional_butoff'] as $id => $member) {
                echo '<div class="shd_ajaxnotify"><input type="checkbox" name="notify[', $id, ']" value="', $id, '"', in_array($id, $selected) ? ' checked="checked"' : '', ' class="input_check" /> ', $member, '</div>';
            }
        }
        echo ']', ']></notify>';
        $content = ob_get_clean();
        return $context['ajax_raw'] = cleanXml($content);
    }
}
function shd_notifications_notify_newreply(&$msgOptions, &$ticketOptions, &$posterOptions)
{
    global $smcFunc, $context, $modSettings, $scripturl;
    // We did actually get a reply? Sometimes shd_modify_ticket_post() is called for other things, not just on reply.
    if (empty($msgOptions['body'])) {
        return;
    }
    // Alternatively, they might be doing a silent update.
    if (!empty($_POST['silent_update']) && shd_allowed_to('shd_silent_update', $ticketOptions['dept'])) {
        return;
    }
    // We're doing various things here, so grab some general details, not just what we may have been passed before.
    $ticketinfo = shd_load_ticket($ticketOptions['id']);
    // $staff is the sum total of staff + ticket starter, subject to visibility of the ticket.
    $staff = shd_get_visible_list($ticketOptions['dept'], $ticketinfo['private'], $ticketinfo['starter_id'], empty($modSettings['shd_admins_not_assignable']), false);
    // Might as well kick this off here.
    $notify_data = array('members' => array(), 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticketOptions['id'] . '.msg' . $msgOptions['id'] . '#msg' . $msgOptions['id'], 'subject' => $ticketinfo['subject'], 'ticket' => $ticketOptions['id'], 'msg' => $msgOptions['id'], 'body' => $msgOptions['body'], 'poster_name' => $posterOptions['name']);
    $members = array();
    // who should get what type of notification, preferences depending
    // Someone replied to MY ticket? And it isn't me? I might want you to tell me about it!
    if (!empty($ticketinfo['starter_id']) && !empty($modSettings['shd_notify_new_reply_own']) && $posterOptions['id'] != $ticketinfo['starter_id'] && in_array($ticketinfo['starter_id'], $staff)) {
        $members[$ticketinfo['starter_id']]['new_reply_own'] = true;
    }
    // So this is a ticket I'm supposed to deal with... has someone said something I missed? (And just in case it's our ticket, don't send another)
    if (!empty($modSettings['shd_notify_new_reply_assigned'])) {
        if (!empty($ticketinfo['assigned_id']) && $posterOptions['id'] != $ticketinfo['assigned_id'] && in_array($ticketinfo['assigned_id'], $staff)) {
            $members[$ticketinfo['assigned_id']]['new_reply_assigned'] = true;
        }
    }
    // So, if you're staff, and you've replied to a ticket before, do you want to be notified this time?
    if (!empty($modSettings['shd_notify_new_reply_previous'])) {
        $query = $smcFunc['db_query']('', '
			SELECT id_member
			FROM {db_prefix}helpdesk_ticket_replies
			WHERE id_ticket = {int:ticket}
			GROUP BY id_member', array('ticket' => $ticketOptions['id']));
        $responders = array();
        while ($row = $smcFunc['db_fetch_row']($query)) {
            $responders[] = $row[0];
        }
        // this shouldn't be nil, ever, because we're replying, so the topic already exists so there's at least one name in there...
        $smcFunc['db_free_result']($query);
        $responders = array_intersect($responders, $staff);
        foreach ($responders as $id) {
            $members[$id]['new_reply_previous'] = true;
        }
    }
    // Do staff just want general notifications about everything? Don't change things if they already had a notice though, this is just for the rabble at the back
    if (!empty($modSettings['shd_notify_new_reply_any'])) {
        foreach ($staff as $id) {
            $members[$id]['new_reply_any'] = true;
        }
    }
    if (empty($members)) {
        return;
    }
    // Get the default preferences
    $prefs = shd_load_user_prefs(false);
    $pref_groups = $prefs['groups'];
    $base_prefs = $prefs['prefs'];
    // Build a list of users -> default prefs
    $member_prefs = array();
    $pref_list = array();
    foreach ($members as $id => $type_list) {
        foreach ($type_list as $type => $value) {
            $member_prefs[$id][$type] = $base_prefs['notify_' . $type]['default'];
            $pref_list['notify_' . $type] = true;
        }
    }
    // Grab pref list from DB for these users and update
    $query = $smcFunc['db_query']('', '
		SELECT id_member, variable, value
		FROM {db_prefix}helpdesk_preferences
		WHERE id_member IN ({array_int:members})
			AND variable IN ({array_string:variables})', array('members' => array_keys($members), 'variables' => array_keys($pref_list)));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        $row['id_member'] = (int) $row['id_member'];
        $variable = substr($row['variable'], 7);
        if (isset($member_prefs[$row['id_member']][$variable])) {
            $member_prefs[$row['id_member']][$variable] = $row['value'];
        }
    }
    $smcFunc['db_free_result']($query);
    // unset $members where member pref doesn't fit
    foreach ($member_prefs as $id => $value) {
        foreach ($value as $pref_id => $pref_item) {
            if (empty($pref_item)) {
                unset($members[$id][$pref_id]);
            }
        }
    }
    // Lastly, get the list of people who wanted to be notified through their preferences - and anyone who wanted to be excluded.
    $overrides = shd_query_monitor_list($ticketOptions['id']);
    foreach ($overrides['always_notify'] as $member_id) {
        $members[$member_id]['monitor'] = true;
    }
    // And apply exclusions
    foreach ($overrides['never_notify'] as $member_id) {
        unset($members[$member_id]);
    }
    // And now, finally, receive the list of possible cases from the notification doodad, and verify against a list of possible people.
    if ($context['can_ping']) {
        if (!empty($_POST['notify']) && is_array($_POST['notify'])) {
            $staff[] = $ticketinfo['starter_id'];
            // Add the ticket starter as a possible candidate.
            foreach ($_POST['notify'] as $id) {
                if (in_array((int) $id, $staff)) {
                    $members[$id]['ping'] = true;
                }
            }
        } elseif (!empty($_REQUEST['list'])) {
            $list = explode(',', $_REQUEST['list']);
            foreach ($list as $id) {
                if (in_array((int) $id, $staff)) {
                    $members[$id]['ping'] = true;
                }
            }
        }
    }
    // Lastly, prevent the reply author getting notified for any reason.
    if (!empty($members[$context['user']['id']])) {
        unset($members[$context['user']['id']]);
    }
    // So, at this point, $members contains a list of the members and a sequence of the possible messages they could get. We need to make some sense of it.
    $notify_data['members'] = array();
    foreach ($members as $member_id => $notify_list) {
        if (empty($notify_list)) {
            continue;
        }
        // Preferences killed all their possible choices.
        // We want the first non empty value on the list, and that's all.
        $item = '';
        foreach ($notify_list as $k => $v) {
            if (!empty($v)) {
                $item = $k;
                break;
            }
        }
        if (!empty($item)) {
            $notify_data['members'][$member_id] = $item;
        }
        // We want the first one only.
    }
    // AAAAAAAAAAAAND WE'RE OFF!
    if (!empty($notify_data['members'])) {
        shd_notify_users($notify_data);
    }
}