<?php
defined('BASEPATH') or exit('No direct script access allowed');

class User_messaging extends MY_Controller
{

    public function __construct()
    {
        parent::__construct();

        $no_logged_methods = array();

        if (empty($this->session->logged) && !in_array($this->router->fetch_method(), $no_logged_methods)) {
            $this->session->set_flashdata('show_login_form', true);
            redirect('engine/error?http_code=403');
        }

        $this->load->model(array('users_inbox_model' => 'inbox_model'));
    }

    public function index()
    {
        //$this->output->enable_profiler();

        $action = $this->input->get('action');
        switch ($action) {
            case 'read':
                $this->read_private_message();
                break;
            case 'write':
                $this->send_message();
                break;
            case 'limits':
                $this->get_limits();
                break;
            default:
                $this->get_inbox_home();
        }
    }

    private function get_inbox_home()
    {
        $pagination_config = $this->_get_pagination_config();

        $offset = $this->input->get('page', true);

        if (empty($offset))
        {
            $offset = 0;
        }

        $pagination_config['per_page']   = 25;
        $pagination_config['total_rows'] = $this->inbox_model->get_pm_count($this->session->id);

        $this->pagination->initialize($pagination_config);

        $auto_messages       = $this->inbox_model->get_auto_messages();

        // Get all inbox messages
        $classicMessages = $this->inbox_model->get_inbox_messages($pagination_config['per_page'], $offset);

        $session_status = $this->session->status_auto_messages;
        $session_status = json_decode($session_status, JSON_OBJECT_AS_ARRAY);


        foreach ($auto_messages as $k => $auto_message) 
        {
            $auto_message->string_type = 'auto_message';
            $key = 'message_'.$auto_message->id;

            if($session_status[$key] == 'deleted')
            {
                unset($auto_messages[$k]);
            }

            if($auto_message->type == 1)
            {
                $ascent = Ygg::get_ascent_timetamp($auto_message->periodicity);
                
                if($auto_message->instant_publish == 0 && date('z-Y', $ascent) == date('z-Y', time()) && $ascent > time()) 
                {
                    unset($auto_messages[$k]);
                }
                else if($auto_message->instant_publish == 0 && $auto_message->last_publish_date > $ascent)
                {
                    unset($auto_messages[$k]);
                }
                else if(time() > $ascent && $ascent > $auto_message->last_publish_date || date('z-Y', $ascent) == date('z-Y', time())) 
                {
                    $auto_message->last_publish_date = $ascent;
                }
            }

        }

       // print_r($auto_messages);
        $mergedArray     = array_merge($auto_messages, $classicMessages);

        usort($mergedArray, function($a, $b) {
            return strcmp($b->last_publish_date, $a->last_publish_date);
        });

        $messages = array_splice($mergedArray, 0, $pagination_config['per_page']);

        //print_r($messages);
        $data['messages'] = $messages;

        $data['total_messages'] = $pagination_config['total_rows'];
        $data['offset']         = $offset;
        $data['limit']          = count($data['messages']);

        $this->load->view('user/inbox/inbox_home', $data);
    }

    private function is_not_allowed_user($private_message_id)
    {
        $id = $this->db->select('id')->where('user_id', $this->session->id)->where('parent_message_id', $private_message_id)->where('state', 0)->get('messages_users')->row()->id;
        if (empty($id)) {
            return true;
        }
        return false;

    }

    public function update_messages_status($action='')
    {
 
        $actions = ['deleted' => null, 'unreaded'  => ['txt' => 'marquer comme non-lu'] , 'readed' => ['txt' => 'marquer comme lu']];

        if ($this->input->method() == 'post' && array_key_exists($action, $actions)) 
        {
            $messages_data = $this->input->post('data');
            $messages_data = json_decode($messages_data, JSON_OBJECT_AS_ARRAY);

            $days = [null, 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
            
            $func = 'set_status_'.$action;

            if($action == 'deleted')
            {
                $regular_messages_id = array();
                $session_status = $this->session->status_auto_messages;
                $session_status = json_decode($session_status, JSON_OBJECT_AS_ARRAY);

                foreach($messages_data as $message)
                {
                    if($message['mtype'] == 'auto')
                    {
                        $result = $this->inbox_model->get_auto_message($message['mid'], 'messages_auto.id, messages_auto.type, messages_auto.periodicity, messages_auto.publish_date, messages_auto.publish_date');

                        # Message périodique
                        if($result->type == 1)
                        {
                            $ascent = Ygg::get_ascent_timetamp($result->periodicity);
                        }

                        $key = 'message_'.$result->id;

                        if(array_key_exists($key, $session_status) && $session_status[$key] == 'deleted')
                        {
                            $this->show_error('Certains des messages selectionnés ont déjà été supprimés');   
                        }
                        else if(array_key_exists($key, $session_status) && $session_status[$key] > $result->publish_date)
                        {
                            if($result->type == 1 && time() > $ascent && $session_status[$key] < $ascent)
                            {  
                              $this->show_error('Vous ne pouvez supprimer un message automatique qu\'après l\'avoir lu.');   
                            }
                            else
                            {
                                $session_status[$key] = 'deleted';
                            }
                        }
                        else 
                        {
                            $this->show_error('Vous ne pouvez supprimer un message automatique qu\'après l\'avoir lu.');   
                        }
                    }
                    else {
                        $regular_messages_id[] = $message['mid'];
                    }
                }

                $this->inbox_model->update_status_auto_message($session_status);
                $this->inbox_model->$func($regular_messages_id);

                $data = array(
                    'action' => 'success',
                    'data' => $session_status
                );
                $this->show_json($data);
            }
            else 
            {
                if(in_array('auto', array_column($messages_data, 'mtype')))
                {
                   $this->show_error('Impossible de '.$actions[$action]['txt'].' un message automatique.');   
                }
                else 
                {
                    $messages_id = array_column($messages_data, 'mid');

                    $this->inbox_model->$func($messages_id);

                    $this->show_json('success');
                }
            }
        }
    }

    public function get_ajax_replies()
    {
        $private_message = intval($this->input->post('pm', true));
        $offset          = intval($this->input->post('offset', true));

        if ($this->is_not_allowed_user($private_message)) {
            $this->send_message_error('Accès refusé vous n\'avez pas l\'autorisation');
        }

        $message_replies = $this->inbox_model->get_replies($private_message, 15, $offset);
        $out             = '';
        foreach ($message_replies as $reply) {
            $data['reply'] = $reply;
            $out .= $this->load->view('ajax_templates/private_message/reply', $data, true);
        }

        $this->output->set_content_type('application/json')->set_output(json_encode(array('html' => $out, 'length' => count($message_replies))));
    }

    public function edit_reply()
    {
        //    $this->output->enable_profiler();
        $reply_id = intval($this->input->post('id', true));

        if ($this->inbox_model->is_owner_reply($reply_id) && isset($reply_id)) {

            $this->form_validation->set_rules('reply_body', 'contenu du message', 'required|min_length[10]|max_length[4000]|xss_clean');

            if ($this->form_validation->run()) {
                $reply = $this->input->post('reply_body');
                $reply = purify($reply);
                $reply = htmlentities($reply);
                // Je suis un porc et j'assume !
                $this->db->where('id', $reply_id)->set('message_body', $reply)->update('messages_replies');
            }

            sizeof($this->form_validation->error_array()) > 0 ? $this->show_error(array_values($this->form_validation->error_array())[0]) : '';

        }

    }

    public function read_message_auto($message_auto_id = '')
    {
        $message = $this->inbox_model->get_auto_message($message_auto_id);
        $status_messages = $this->session->status_auto_messages;
        $status_messages = json_decode($status_messages, JSON_OBJECT_AS_ARRAY);
        
        if(count($status_messages) == 0 || !is_array($status_messages))
        {
            $status_messages = array();
        }

        $message_id = 'message_'.$message_auto_id;
        
        if($message->type == 1)
        {
            $ascent = Ygg::get_ascent_timetamp($message->periodicity);
        }

        if(!array_key_exists($message_id, $status_messages) || $status_messages[$message_id] < $message->publish_date 
            || ($message->type == 1 && time() > $ascent && $status_messages[$message_id] < $ascent))
        {
            $this->inbox_model->viewed_auto_message($message_auto_id);
            $this->inbox_model->increment_views_message_auto($message_auto_id);
        }

        $status_messages['message_'.$message_auto_id] = time();
        $this->inbox_model->update_status_auto_messages($status_messages);

        $data['auto_message'] = $message;
        $this->load->view('user/inbox/inbox_read_message_auto', $data);
    }

    public function get_message()
    {
        $message_id = $this->input->get('id');

        if (!filter_var($message_id, FILTER_VALIDATE_INT)) {
            $this->show_error('Paramètre message_id invalide');
        }

        $message = $this->inbox_model->get_reply_message($message_id);

        if (empty($message->id)) {
            $this->show_error('Message inexistant');
        }

        if ($message->publisher_id != $this->session->id) {
            $this->show_error('Impossible de charger un message qui ne vous appartient pas');
        }

        $this->load->helper('minify');

        $html = minify_html(html_entity_decode($message->message_body));
        $this->output->set_content_type('application/json')->set_output(json_encode(array('html' => $html)));
    }

    public function delete_action()
    {
        $del_type = $this->input->get('type');
        $tid      = intval($this->input->get('target_id'));

        if (isset($del_type) && isset($tid)) {
            // We want to "delete" an entire private message
            if ($del_type == 'private_message') {

                // We want to "delete" a reply
            } else if ($del_type == 'reply') {
                $this->inbox_model->is_owner_reply($tid) ? $this->inbox_model->delete_reply($tid) : '';
                // $this->action_success();
            }

        }
    }

    public function read_private_message()
    {
        // Send form action
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            //   $this->form_validation->set_rules('message_object', 'objet du message', 'required');
            $this->form_validation->set_rules('reply_body', 'contenu du message', 'required|min_length[10]|max_length[4000]|xss_clean');
            $this->form_validation->set_rules('private_message_id', 'private_message_id', 'required|integer');

            if ($this->form_validation->run()) {

                $reply_body         = htmlentities(purify($this->input->post('reply_body')));
                $private_message_id = $this->input->post('private_message_id');

                if ($this->is_not_allowed_user($private_message_id)) {
                    $this->send_message_error('Accès refusé vous n\'avez pas l\'autorisation');
                }

                $reply_id = $this->inbox_model->new_reply($private_message_id, $reply_body);

                $this->load->helper('minify');

                $data['reply_body']         = $reply_body;
                $data['reply_id']           = $reply_id;
                $data['private_message_id'] = $private_message_id;
                // Buil ajax response
                $html = minify_html($this->load->view('ajax_templates/private_message/my_reply', $data, true));

                $this->output->set_content_type('application/json')->set_output(json_encode(array('html' => $html)));
            }

            // Handles form_validation errors in Json
            sizeof($this->form_validation->error_array()) > 0 ? $this->show_error(array_values($this->form_validation->error_array())[0]) : '';

        } else {
            $private_message_id = $this->input->get('id');

            $data['private_message'] = $this->inbox_model->get_private_message($private_message_id);

            if ($this->is_not_allowed_user($private_message_id)) {
                $this->send_message_error('Acces refusé vous n\'avez pas l\'autorisation');
            } else {
                $data['private_replies_message'] = $this->inbox_model->get_replies($private_message_id);
                $data['count_replies']           = $this->inbox_model->get_count_replies($private_message_id);

                $this->inbox_model->mark_as_read($private_message_id);
            }

            $this->load->view('user/inbox/inbox_read_message', $data);
        }
    }

    public function report_message()
    {
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            //  $this->output->enable_profiler();
            $message_id    = intval($this->input->post('message_id'));
            $del_message   = $this->input->post('del_message');
            $ignore_sender = $this->input->post('ignore_sender');
            $reason        = $this->input->post('reason');

            $private_message_data = $this->inbox_model->getMessageDataFromReply('publisher_id, parent_message_id', $message_id);
            $publisher_id         = $private_message_data->publisher_id;
            $private_message_id   = $private_message_data->parent_message_id;

            if (isset($_POST['ignore_sender'])) {
                $ignoredList = $this->db->select('ignored')->where('id', $this->session->id)->get('users')->row()->ignored;
                $ignoredList = json_decode($ignoredList, JSON_OBJECT_AS_ARRAY);

                if (!array_key_exists($publisher_id, $ignoredList)) {
                    $isUserExists = $this->db->select('id')->where('id', $publisher_id)->get('users')->num_rows() > 0;

                    if ($isUserExists) {

                        // On ajoute l'utilisateur à la liste avec la date d'ajout
                        if (!is_array($ignoredList)) {
                            $ignoredList                = array();
                            $ignoredList[$publisher_id] = now();
                        } else {
                            $ignoredList[$publisher_id] = now();
                        }

                        $ignoredList = json_encode($ignoredList);
                        $this->db->where('id', $this->session->id)->set('ignored', $ignoredList)->update('users');
                    }

                }

                if (isset($_POST['del_message'])) {
                    $this->inbox_model->remove_private_messages(array($private_message_id));
                }

                if (isset($reason) && strlen($reason)) {
                    $this->show_error('le motif du signalement excède 250 caractères');
                }

            }
        }
    }

    public function send_message()
    {
        $recipient_id = $this->input->get('recipient_id');

        $data['single_recipient'] = false;

        if (isset($recipient_id) && filter_var($recipient_id, FILTER_VALIDATE_INT)) {
            // If users try to send a PM to itself
            if ($recipient_id == $this->session->id) {
                $this->action_send_message('Impossible de s\'envoyer un message à soit même');
            } else {
                $recipient_nickname = $this->inbox_model->get_recipient_nickname($recipient_id);
                // If ID user doesn't exists
                if (empty($recipient_nickname)) {
                    $this->action_send_message('Cet identifiant utilisateur n\'existe pas');
                } else {
                    $data['single_recipient_id']       = $recipient_id;
                    $data['single_recipient_nickname'] = $recipient_nickname;
                    $data['single_recipient']          = true;
                }
            }
        }
        // Send form action
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
            $this->action_send_message($data['single_recipient']);
        } else {
            $this->load->view('user/inbox/inbox_new_message', $data);
        }
    }

    private function action_send_message($single_recipient = false)
    {
        $this->form_validation->set_rules('recipients[]', 'destinataires', 'integer|required');

        // Set validation rules
        $this->form_validation->set_rules('message_object', 'objet du message', 'required|xss_clean');
        $this->form_validation->set_rules('message_body', 'contenu du message', 'required');

        if ($this->form_validation->run()) {
            // Get values
            $recipients     = array_map('intval', $this->input->post('recipients'));
            $message_object = strip_tags($this->input->post('message_object'));
            $message_body   = htmlentities(purify($this->input->post('message_body')));

            if (count($recipients) > 5) {
                $this->show_error('Impossible d\'envoyer un MP à plus de 5 destinataires');
            }

            if (in_array($this->session->id, $recipients)) {
                $this->show_error('Impossible de s\'inclure dans la liste des destinataires');
            }

            $recipients_list = $this->inbox_model->get_recipients_list($recipients);
            // Add the current session user to recipients list
            $recipient_self->id           = $this->session->id;
            $recipient_self->nickname     = $this->session->nickname;
            $recipient_self->is_expeditor = true;
            $recipients_list[]            = $recipient_self;

            $recipients_list_id = array();

            $seconds = array(
                '24hours' => 3600,
                '4days'   => 345600,
                '1week'   => 604800,
                '2weeks'  => 1209600,
                '1month'  => 2629746,
                '3months' => 7889238,
            );

            foreach ($recipients_list as $recipient) {
                if ($recipient->id != $this->session->id) {
                    $recipient_settings = json_decode($recipient->settings, JSON_OBJECT_AS_ARRAY);
                    $ignoredList        = json_decode($recipient->ignored, JSON_OBJECT_AS_ARRAY);

                    if (array_key_exists($this->session->id, $ignoredList)) {
                        $this->show_error('Impossible de communiquer avec l\'utilisateur <strong>' . $recipient->nickname . '</strong>');
                    } else if (isset($recipient_settings['pm']['condition_sender_age']) && $recipient_settings['pm']['condition_sender_age'] != 'nocondition') {
                        $sender_age = $recipient_settings['pm']['condition_sender_age'];

                        $timestamp_pm = now() - $seconds[$sender_age];

                        if ($this->session->join_date >= $timestamp_pm) {
                            $this->show_error('L\'ancienneté de votre compte ne vous permet pas de communiquer avec l\'utilisateur <strong>' . $recipient->nickname . '</strong>');
                        }
                    } else if ($recipient_settings['pm']['enable'] != 1) {
                        $this->show_error('<strong>' . $recipient->id . '</strong> a désactivé sa boite de réception et ne souhaite pas recevoir de nouveaux messages');
                    }

                    $recipients_list_id[] = $recipient->id;
                }
            }

            // Verify if recipients are valids
            if (count(array_diff($recipients, $recipients_list_id)) != 0) {

                $this->show_error('La liste des destinataires est invalide');
            }

            // Create private message
            $private_message_id = $this->inbox_model->new_private_message($message_object, $recipients_list);

            // Add reply
            $this->inbox_model->new_reply($private_message_id, $message_body);

            $this->session->set_flashdata('pm_sent', true);

            $this->output->set_content_type('application/json')->set_output(json_encode(array('message_id' => $private_message_id)));
        }

        // Handles form_validation errors in Json
        sizeof($this->form_validation->error_array()) > 0 ? $this->show_error(array_values($this->form_validation->error_array())[0]) : '';
    }

    public function search_users()
    {
        $queryP = $this->input->get('q', true);

        $list = array();

        if (!empty($queryP) && strlen($queryP) >= 3) {
            $query = 'SELECT * FROM users WHERE MATCH(\'@nick ' . $this->_escape($queryP . '*') . '| ' . $this->_escape($queryP) . ' \') limit 10';
            // Open Sphinx connection
            $conn = new mysqli($this->config->item('sphinx_server'), null, null, null, $this->config->item('sphinx_server_port'));

            if ($conn->connect_error) {
                throw new Exception('Erreur avec Sphinx : ' . $conn->connect_error, $conn->connect_error);
            }

            $query_search = $conn->query($query);
            $results      = array();
            // Retrieve the Ids
            while ($row = $query_search->fetch_assoc()) {
                $results[] = $row['id'];
            }

            $query_search->free_result();
            $ids = join('\',\'', $results);
            // Mysql query to get the nicknames
            // id, avatar, rank, uploaded, downloaded, last_activity_date, nickname, country
            $sql = "SELECT id, avatar, rank, uploaded, downloaded, last_activity_date, nickname, country FROM users WHERE id IN ('$ids') ORDER BY FIELD (users.id,'$ids')";

            $results = $this->db->query($sql)->result();

            foreach ($results as $result) {
                $list[] = ['id' => $result->id, 'text' => $result->nickname];
            }
        }

        $this->output->set_content_type('application/json')->set_output(json_encode($list));
    }

    public function can_receive()
    {
        $user_id = intval($this->input->get('user_id', true));

        if (isset($user_id)) {
            if ($this->session->id == $user_id) {
            	 $this->output->set_content_type('application/json');
                $this->output->set_output(json_encode(array('response' => 'negative', 'msg' => 'Impossible de s\'inclure dans la liste des destinataires')));
            } else {
                $recipient_data = $this->db->select('nickname, settings, ignored')->where('id', $user_id)->get('users')->row();
                $nickname       = $recipient_data->nickname;

                $recipient_settings = json_decode($recipient_data->settings, JSON_OBJECT_AS_ARRAY);
                $ignoredList        = json_decode($recipient_data->ignored, JSON_OBJECT_AS_ARRAY);

                if (array_key_exists($this->session->id, $ignoredList)) {
                    $this->output->set_content_type('application/json')->set_output(json_encode(array('response' => 'negative', 'msg' => 'Impossible de communiquer avec l\'utilisateur <strong>' . $nickname . '</strong>')));
                } else {
                    if ($recipient_settings['pm']['enable'] != 1) {
                        $this->output->set_content_type('application/json')->set_output(json_encode(array('response' => 'negative', 'msg' => '<strong>' . $nickname . '</strong> a désactivé sa boite de réception et ne souhaite pas recevoir de nouveaux messages')));
                    } else if (isset($recipient_settings['pm']['condition_sender_age']) && $recipient_settings['pm']['condition_sender_age'] != 'nocondition') {
                        $sender_age = $recipient_settings['pm']['condition_sender_age'];

                        $seconds = array
                            (
                            '24hours' => 3600,
                            '4days'   => 345600,
                            '1week'   => 604800,
                            '2weeks'  => 1209600,
                            '1month'  => 2629746,
                            '3months' => 7889238,
                        );

                        $timestamp_pm = now() - $seconds[$sender_age];

                        if ($this->session->join_date >= $timestamp_pm) {
                            $this->output->set_content_type('application/json');
                            $this->output->set_output(json_encode(array('response' => 'negative', 'msg' => 'L\'ancienneté de votre compte ne vous permet pas de communiquer avec l\'utilisateur <strong>' . $recipient->nickname . '</strong>')));
                        }
                    }
                }
            }
        }
    }

    private function send_message_error($error)
    {
        $this->session->set_flashdata('send_message_error', $error);
        // It redirects on error
        redirect(site_url('user_messaging'));
    }

}
