/**
 * 消息端点。
 *
 * 此控制器处理点对点，组及消息消息。为三类消息提供发送及查询功能。
 */
var express = require('express');
var router = express.Router();

var http = require('http');
var getui = require('getui');
var log = require('../util/log.js');
var objectUtil = require("../util/objectUtil.js");

var smRepo = require("../repository/system.msg.repo.js");
var pmRepo = require('../repository/private.msg.repo.js');
var gmRepo = require("../repository/group.msg.repo.js");
var nmRepo = require("../repository/notify.msg.repo.js");
var statsRepo = require("../repository/stats.msg.repo.js");
var userRepo = require("../repository/doctor.repo.js");
var groupRepo = require("../repository/group.repo.js");
var searchRepo = require('../repository/search.repo.js');

var APIv1 = require('../include/endpoints').APIv1;
var CONTENT_TYPES = require('../include/commons').CONTENT_TYPE;
var GROUP_TYPE = require('../include/commons').GROUP_TYPE;
var PLATFORMS = require('../include/commons').PLATFORM;

var MAX_INT = 9007199254740992;

var DEFAULT_PAGE_SIZE = 100;

//--------------------------------------------------------------//
//----------------------------消息发送----------------------------//
//--------------------------------------------------------------//

/**
 * 发送System消息。
 *
 * 请求URL：
 *  /chats/sm
 *
 * 消息格式：
 *  {
 *      to: "Rose",
 *      title: "System Message",
 *      summary: "You have new job",
 *      contentType: "1",
 *      content: "The patient has been followed in the scheduler, please make new follow plan as soon as possible."
 *  }
 *
 * @param message
 */
router.post(APIv1.Chats.SM, function (req, res) {
    // 检查消息体及消息格式是否正确
    var message = req.body;
    if (!objectUtil.isJsonObject(message)) {
        throw {httpStatus: 406, message: 'Problems parsing JSON.'}
    }

    // 字段判断
    var testing = objectUtil.fieldsCheck(message, "to", "title", "summary", "contentType", "content");
    if (!testing.pass) {
        throw {httpStatus: 406, message: testing.message}
    }

    // 消息处理
    userRepo.getUserStatus(message.to, function (err, rows) {
        if (err) {
            console.log("Lookup system message receiver failed: ", err);

            res.status(500).send({message: "Lookup system message receiver failed."});
            return;
        }

        if (rows.length == 0) {
            res.status(404).send({message: "User not found: " + message.to});
            return;
        }

        var pushable = rows.length > 0 && rows[0].is_online;
        var notifyMessage = JSON.stringify({type: 'system_msg', data: message.content});
        var userStatus = rows[0];

        // 保存该条推送信息
        smRepo.save(message.to,
            message.contentType,
            message.title,
            message.summary,
            message.content,
            function (err, result) {
                if (err) {
                    log.error("Save system notify message failed, ", err);

                    res.status(500).send({message: "Save system notify message failed."});
                } else {
                    // 先结束网络连接，再处理后续操作，减少客户端等待
                    res.status(200).send();

                    // 保存通知到数据库中
                    nmRepo.save(message.to,
                        message.contentType,
                        message.title,
                        message.summary,
                        notifyMessage,
                        pushable,
                        function (err, result) {
                            if (err) {
                                log.error("Save system notify message failed, ", err);

                                res.status(500).send({message: "Save system notify message failed."});
                            } else {
                                if (pushable) {
                                    if (userStatus.platform === PLATFORMS.iOS) {
                                        getui.pushAPN(message.to, userStatus.token, message.contentType, message.title, message.content, notifyMessage,
                                            function (err, result) {
                                                err != null ? console.log(err) : console.log(result);
                                            });
                                    } else if (userStatus.platform === PLATFORMS.Android) {
                                        getui.pushAndroid(userStatus.client_id, message.contentType, message.title, message.content, notifyMessage, userStatus.status,
                                            function (err, result) {
                                                err != null ? console.log(err) : console.log(result);
                                            });
                                    }
                                }
                            }
                        });
                }
            });
    });
});

/**
 * 处理Private消息。处理流程分：
 * 1 解析消息，并保存到数据库
 * 2 更新消息统计数据
 * 3 获取目标的状态并构建通知消息，如果用户在线就推送通知消息
 *
 * 请求URL：
 *  /chats/pm
 *
 * 消息格式：
 *  {
 *      from: sand,
 *      to: Rose,
 *      contentType: "1,2,3,4",
 *      content: "Please follow the patient as soon as possible."
 *  }
 *
 * @param message
 */
router.post(APIv1.Chats.PM, function (req, res) {
    // 检查消息体及消息格式是否正确
    var message = req.body;
    if (!objectUtil.isJsonObject(message)) {
        throw {httpStatus: 406, message: 'Problems parsing JSON.'}
    }

    // 字段判断
    var testing = objectUtil.fieldsCheck(message, "from", "to", "contentType", "content");
    if (!testing.pass) {
        throw {httpStatus: 406, message: testing.message}
    }

    // 处理消息
    userRepo.isExist(message.to, function (err, rows) {
        if (err) {
            console.log('Lookup receiving users failed: ', err);

            res.status(500).send({message: 'Lookup receiving users failed.'});
            return;
        }

        if (rows.length == 0) {
            res.status(404).send({message: 'Receiving users not found.'});
            return;
        }

        // 保存消息
        var tempContent = message.contentType === CONTENT_TYPES.Article ? JSON.stringify(message.content) : message.content;
        pmRepo.save(message.to, message.from, message.contentType, tempContent, function (err, result) {
            if (err) {
                res.status(500).send({message: 'Save private message failed.'});
                return;
            }

            // 结束网络连接，后续操作继续执行
            pmRepo.findOneMessage(result.insertId, function (err, msg) {
                if (err) {
                    res.status(500).send("Save private message success, but return last message failed.");
                } else {
                    var message = fillMessages(msg);
                    res.status(200).send(message);
                }
            });

            // 更新自身的聊天统计信息
            statsRepo.updatePrivateChatSummary(message.from, message.to, message.from, message.contentType, message.content, function (err, result) {
                if (err) log.error(err);
            });

            // 更新对端的聊天统计信息
            statsRepo.updatePrivateChatSummary(message.to, message.from, message.from, message.contentType, message.content, function (err, result) {
                if (err) log.error(err);
            });

            // 获取对方状态，即对端的系统平台，token等信息，并推送通知消息给对端
            userRepo.getUserStatus(message.to, function (err, result) {
                if (err) {
                    log.error('Get target user status for private message failed： ' + message.to);
                    return;
                }

                // 构建通知消息
                var title = '新消息';
                var content = '';
                if (message.contentType === CONTENT_TYPES.PlainText) {
                    content = message.content;
                } else if (message.contentType === CONTENT_TYPES.Image) {
                    content = '[图片]';
                } else if (message.contentType === CONTENT_TYPES.Audio) {
                    content = '[语音]';
                } else {
                    content = '接收到一条新消息';
                }

                var pushable = false;
                var target;
                if (result.length > 0) {
                    target = result[0];
                    if (target.is_online) {
                        pushable = true;
                    }
                }

                var notifyMessage = JSON.stringify({type: 'p2p_msg', from_uid: message.from});

                // 保存通知消息到数据库中并根据用户在线状态推送此消息
                nmRepo.save(message.to, message.contentType, title, content, notifyMessage, pushable, function (err, result) {
                    if (err) {
                        log.error('Save private notify message failed, ', err);
                    } else {
                        if (pushable === true) {
                            if (target.platform === PLATFORMS.iOS) {
                                getui.pushAPN(message.to,
                                    target.token,
                                    message.contentType,
                                    title,
                                    content,
                                    notifyMessage,
                                    function (err, result) {
                                        if (err != null) {
                                            console.log(err);
                                        } else {
                                            console.log(result);
                                        }
                                    });
                            } else if (target.platform === PLATFORMS.Android) {
                                getui.pushAndroid(target.client_id,
                                    message.contentType,
                                    title,
                                    content,
                                    notifyMessage,
                                    target.status,
                                    function (err, result) {
                                        if (err != null) {
                                            console.log(err);
                                        } else {
                                            console.log(result);
                                        }
                                    });
                            }
                        }
                    }
                });
            });
        });
    });
});

/**
 * 处理讨论组消息。
 *
 * 请求URL：
 *  /chats/gm
 *
 * 消息格式：
 *  {
 *      from: "sand",                       // 发送者id
 *      at: "Rose",                         // @人
 *      group: "DiscussionGroupId",         // 所在组
 *      groupType: "1 or 2",                // 组类型：行政团队或讨论组
 *      contentType: "1,2,3",               // 内容类型
 *      content: "The patient mess me up"   // 内容
 *  }
 *
 * @param message
 */
router.post(APIv1.Chats.GM, function (req, res) {
    // 检查消息体及消息格式是否正确
    var message = req.body;
    if (!objectUtil.isJsonObject(message)) {
        throw {httpStatus: 406, message: 'Problems parsing JSON.'};
    }

    // 字段判断
    var testing = objectUtil.fieldsCheck(message, 'from', 'at', 'group', 'groupType', 'contentType', 'content');
    if (!testing.pass) {
        throw {httpStatus: 406, message: testing.message}
    }

    // 消息处理
    groupRepo.isGroupMember(message.group, message.groupType, message.from, function (err, result) {
        if (err) {
            log.error('Check group member failed: ', err);

            res.status(500).send({message: 'Check group member failed.'});
            return;
        }

        if (result.length == 0) {
            res.status(404).send({message: 'Member with id "' + message.from + '" is not in group "' + message.group + '"'});
            return;
        }

        // 保存群组消息
        gmRepo.save(message.from, message.group, message.at, message.contentType, message.content, function (err, insertedRow) {
            if (err) {
                log.error('Save group message failed: ', err);

                res.status(500).send({message: 'Save group message failed.'});
                return;
            }

            gmRepo.findOneMessage(insertedRow.insertId, function (err, groupMsg) {
                if (err) {
                    log.error("Save group message success, but return this message failed.");

                    res.status(500).send({message: "Save group message success, but return this message failed."});
                }
                // 关闭网络连接后执行后续操作
                res.status(200).send(fillMessages(groupMsg));
            });

            // 更新组内统计信息
            statsRepo.updateGroupChatSummary(message.from, message.group, message.from, 0, message.contentType, message.content, false, function (err, result) {
                if (err) log.error(err);
            });

            // 推送通知消息给群组成员
            groupRepo.getMembers(message.group, message.groupType, function (err, members) {
                if (err) {
                    log.error('Get group members failed: ', err);
                    return;
                }

                if (members.length == 0) {
                    log.warn('No members in group ', message.group,
                        message.groupType === GROUP_TYPE.AdminTeam ? " of admin team." : "of discussion group.");

                    return;
                }

                // 逐个推送通知
                for (var i = 0; i < members.length; i++) {
                    var member = members[i];
                    if (member.user_id === message.from){
                        continue;
                    }

                    (function (user_id) {
                        userRepo.getUserStatus(user_id, function (err, result) {
                            if (err) {
                                console.error('Get group member status failed: ', err);
                                return;
                            }

                            var title = '';
                            var content = '';
                            if (message.contentType === CONTENT_TYPES.PlainText) {
                                title = '群组消息';
                                content = message.content;
                            } else if (message.contentType === CONTENT_TYPES.Image) {
                                title = '群组消息';
                                content = '[图片]';
                            } else if (message.contentType === CONTENT_TYPES.Audio) {
                                title = '群组消息';
                                content = '[语音]';
                            } else {
                                title = '群组消息';
                                content = '接收到一条新消息';
                            }

                            var pushable = result.length > 0 && result[0].is_online === 1;
                            var notifyMessage = JSON.stringify({type: 'group_msg', gid: message.group});

                            // 发送并保存通知到数据库中
                            if (pushable) {
                                var userStatus = result[0];

                                if (userStatus.platform === PLATFORMS.iOS) {
                                    getui.pushAPN(user_id,
                                        userStatus.token,
                                        message.contentType,
                                        title,
                                        content,
                                        notifyMessage,
                                        function (err, result) {
                                            err != null ? console.error(err) : console.log(result);

                                            // 这段代码重复
                                            nmRepo.save(user_id,
                                                message.contentType,
                                                title,
                                                content,
                                                notifyMessage,
                                                err != null ? 0 : 1,
                                                function (err, result) {
                                                    if (err) {
                                                        console.log('Save group notify message failed: ', err);
                                                    } else {

                                                    }
                                                });
                                        });
                                } else if (userStatus.platform === PLATFORMS.Android) {
                                    getui.pushAndroid(data.client_id,
                                        message.contentType,
                                        title,
                                        content,
                                        notifyMessage,
                                        userStatus.status,
                                        function (err, result) {
                                            err != null ? console.error(err) : console.log(result);

                                            // 这段代码重复
                                            nmRepo.save(user_id,
                                                message.contentType,
                                                title,
                                                content,
                                                notifyMessage,
                                                err != null ? 0 : 1,
                                                function (err, result) {
                                                    if (err) {
                                                        console.log('Save group notify message failed: ', err);
                                                    } else {

                                                    }
                                                });
                                        });
                                }
                            } else {
                                // 这段代码重复
                                nmRepo.save(user_id,
                                    message.contentType,
                                    title,
                                    content,
                                    notifyMessage,
                                    0,
                                    function (err, result) {
                                        if (err) {
                                            console.log('Save group notify message failed: ', err);
                                        } else {

                                        }
                                    });
                            }
                        });

                        // 统计'@'信息
                        var at = message.at == user_id ? 1 : 0;

                        statsRepo.updateGroupChatSummary(user_id,
                            message.group,
                            message.from,
                            at,
                            message.contentType,
                            message.content,
                            true,
                            function (err, result) {
                                if (err) console.log(err);
                            });
                    })(member.user_id);
                }
            });
        });
    });
});

//--------------------------------------------------------------//
//----------------------------消息提取----------------------------//
//--------------------------------------------------------------//

/**
 * 获取参与的聊天列表，包括：点对点，@我，参与的讨论组，系统消息等。
 *
 * 请求URL：
 *  /chats/list?user_id=sand
 */
router.get(APIv1.Chats.List, function (req, res) {
    var userId = req.query.user_id;
    if (userId === null) {
        throw {httpStatus: 406, message: 'Missing fields.'};
    }

    // 与患者的私信
    pmRepo.findAllP2PWithPatient(userId, function (err, patients) {
        if (err) {
            log.error('Get chat list with patient failed: ', err);

            res.status(500).send({message: 'Get chat list with patient failed.'});
            return;
        }

        var chats = {patients: [], doctors: [], groups: []};
        for (var i = 0; i < patients.length; i++) {
            var patient = patients[i];
            chats.patients.push({
                code: patient.code,
                name: patient.name,
                birthday: patient.birthday,
                sex: patient.sex,
                avatar: patient.photo == null ? "" : patient.photo,
                newMessageCount: patient.new_msg_count,
                lastContentType: patient.last_content_type,
                lastContent: patient.last_content,
                timestamp: objectUtil.timestampToLong(patient.timestamp)
            });
        }

        // 含有患者的群
        gmRepo.findAllGroupsWithPatient(userId, function (err, groups) {
            if (err) {
                log.error('Get group list with patient failed: ', err);

                res.status(500).send({message: 'Get group list with patient failed.'});
                return;
            }

            for (var i = 0; i < groups.length; i++) {
                var group = groups[i];

                // 过滤掉医生间的求助团队
                if(group.group_type === 2) continue;

                chats.groups.push({
                    code: group.code,
                    name: group.name,
                    groupType: group.msg_type,
                    newMessageCount: group.new_msg_count,
                    lastContentType: group.last_content_type,
                    lastContent: group.last_content,
                    timestamp: objectUtil.timestampToLong(group.timestamp)
                });
            }

            // 医生间的私聊
            pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) {
                if (err) {
                    log.error('Get chat list with doctor failed: ', err);

                    res.status(500).send({message: 'Get chat list with doctor failed.'});
                    return;
                }

                for (var i = 0; i < doctors.length; i++) {
                    var doctor = doctors[i];
                    chats.doctors.push({
                        code: doctor.code,
                        name: doctor.name,
                        sex: doctor.sex,
                        avatar: doctor.photo === null ? "" : doctor.photo,
                        newMessageCount: doctor.new_msg_count,
                        lastContentType: doctor.last_content_type,
                        lastContent: doctor.last_content,
                        timestamp: objectUtil.timestampToLong(doctor.timestamp)
                    });
                }

                // 获取医生间的组
                gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) {
                    if (err) {
                        log.error('Get group list with doctor failed: ', err);

                        res.status(500).send({message: 'Get group list with doctor failed.'});
                        return;
                    }

                    for (var i = 0; i < groups.length; i++) {
                        var group = groups[i];
                        chats.groups.push({
                            code: group.code,
                            name: group.name,
                            groupType: group.group_type, // 行政团队 or 求助
                            newMessageCount: group.new_msg_count,
                            lastContentType: group.last_content_type,
                            lastContent: group.last_content,
                            timestamp: objectUtil.timestampToLong(group.timestamp)
                        });
                    }

                    res.status(200).send(chats);
                });
            });
        })
    });
});

/**
 * 获取与患者的聊天列表，包括：P2P，参与的讨论组和行政团队。
 *
 * 请求URL：
 *  /chats/list/patient
 */
router.get(APIv1.Chats.ListWithPatient, function (req, res) {
    var userId = req.query.user_id;
    if (userId === null) {
        throw {httpStatus: 406, message: 'Missing fields.'};
    }

    pmRepo.findAllP2PWithPatient(userId, function (err, patients) {
        if (err) {
            log.error('Get chat list with patient failed: ', err);

            res.status(500).send({message: 'Get chat list with patient failed.'});
            return;
        }

        var chats = {patients: [], groups: []};
        for (var i = 0; i < patients.length; i++) {
            var patient = patients[i];
            chats.patients.push({
                code: patient.code,
                name: patient.name,
                birthday: patient.birthday,
                sex: patient.sex,
                avatar: patient.photo == null ? "" : patient.photo,
                newMessageCount: patient.new_msg_count,
                lastContentType: patient.last_content_type,
                lastContent: patient.last_content,
                timestamp: objectUtil.timestampToLong(patient.timestamp)
            });
        }

        gmRepo.findAllGroupsWithPatient(userId, function (err, groups) {
            if (err) {
                log.error('Get group list with patient failed: ', err);

                res.status(500).send({message: 'Get group list with patient failed.'});
                return;
            }

            for (var i = 0; i < groups.length; i++) {
                var group = groups[i];

                // 过滤掉医生间的求助团队
                if(group.group_type === 2) continue;

                chats.groups.push({
                    code: group.code,
                    name: group.name,
                    groupType: group.msg_type,
                    newMessageCount: group.new_msg_count,
                    lastContentType: group.last_content_type,
                    lastContent: group.last_content,
                    timestamp: objectUtil.timestampToLong(group.timestamp)
                });
            }

            res.status(200).send(chats);
        })
    });
});

/**
 * 获取与医生的聊天列表，包括：点对点，参与的讨论组。
 *
 * 请求URL：
 *  /chats/list/doctor
 */
router.get(APIv1.Chats.ListWithDoctor, function (req, res) {
    var userId = req.query.user_id;
    if (userId === null) {
        throw {httpStatus: 406, message: 'Missing fields.'};
    }

    // 先获取医生间的私聊
    pmRepo.findAllP2PWithDoctor(userId, function (err, doctors) {
        if (err) {
            log.error('Get chat list with doctor failed: ', err);

            res.status(500).send({message: 'Get chat list with doctor failed.'});
            return;
        }

        var chats = {doctors: [], groups: []};
        for (var i = 0; i < doctors.length; i++) {
            var doctor = doctors[i];
            chats.doctors.push({
                code: doctor.code,
                name: doctor.name,
                sex: doctor.sex,
                avatar: doctor.photo === null ? "" : doctor.photo,
                newMessageCount: doctor.new_msg_count,
                lastContentType: doctor.last_content_type,
                lastContent: doctor.last_content,
                timestamp: objectUtil.timestampToLong(doctor.timestamp)
            });
        }

        // 再获取医生间的组
        gmRepo.findAllGroupsWithDoctor(userId, function (err, groups) {
            if (err) {
                log.error('Get group list with doctor failed: ', err);

                res.status(500).send({message: 'Get group list with doctor failed.'});
                return;
            }

            for (var i = 0; i < groups.length; i++) {
                var group = groups[i];
                chats.groups.push({
                    code: group.code,
                    name: group.name,
                    groupType: group.group_type, // 行政团队 or 求助
                    newMessageCount: group.new_msg_count,
                    lastContentType: group.last_content_type,
                    lastContent: group.last_content,
                    timestamp: objectUtil.timestampToLong(group.timestamp)
                });
            }

            res.status(200).send(chats);
        });
    });
});

/**
 * 获取最近聊天对象：包括患者，医生与讨论组。客户端自行根据需要提取患者、医生或讨论组数据。
 *
 * 请求URL：
 *  /chats/recent?user_id=0de7295862dd11e69faffa163e8aee56&days=7
 *
 * 参数：
 *  user_id: 用户ID
 *  target_type: 对象类型，1患者，2医生，3讨论组
 *  days: 最近天数
 */
router.get(APIv1.Chats.Recent, function (req, res) {
    var userId = req.query.user_id;
    var days = req.query.days;
    if (userId === null) {
        throw {httpStatus: 406, message: 'Missing field: user_id'};
    }

    if (days === null) {
        throw {httpStatus: 406, message: 'Missing field: days'};
    }

    statsRepo.getRecentChats(userId, days, function (err, result) {
        if (err) {
            log.error('Get recent chat objects failed: ', err);

            res.status(500).send({message: 'Get recent chat objects failed.'});
            return;
        }

        var data = {patients: [], doctors: [], groups: []};
        if (result.length === 0) {
            res.status(200).send(data);
            return;
        }

        for (var i = 0; i < result.length; ++i) {
            var row = result[i];
            if (row.type.indexOf('patient') > -1) {
                data.patients.push({
                    code: row.code,
                    name: row.name,
                    birthday: row.birthday === null ? "" : row.birthday,
                    sex: row.sex,
                    avatar: row.photo === null ? "" : row.photo
                });
            } else if (row.type.indexOf('doctor') > -1) {
                data.doctors.push({
                    code: row.code,
                    name: row.name,
                    birthday: row.birthday === null ? "" : row.birthday,
                    sex: row.sex,
                    avatar: row.photo === null ? "" : row.photo
                });
            } else if (row.type.indexOf('group') > -1) {
                data.groups.push({
                    code: row.code,
                    name: row.name
                });
            }
        }

        res.status(200).send(data);
    });
});

/**
 * 获取私信。倒序排列。
 *
 * 参数：
 *  user_id 必须，医生ID
 *  peer_id 必须，对方医生ID
 *  content_type 必须，消息类型
 *  message_start_id 可选，消息的起始ID，如果为空从最新的一条开始获取
 *  message_end_id 可选，消息的结束ID，如果为空从第一条开始获取
 *  count 可选，消息数量，如果不指定、小于零或大于50，默认为100条。若message_start_id与message_end_id均不为空，则此参数无效，方法是设置为10000条
 *  closed_interval 消息范围是否使用闭区间
 *
 * 请求URL：
 *  /chats/pm?user_id=sand&peer_id=Rose&content_type=2&message_start_id=10000&message_end_id=0&count=20&closed_interval=false
 */
router.get(APIv1.Chats.PM, function (req, res) {
    var userId = req.query.user_id;
    var peerId = req.query.peer_id;
    var contentType = req.query.content_type;
    var msgStartId = !req.query.message_start_id ? MAX_INT : parseInt(req.query.message_start_id);
    var msgEndId = !req.query.message_end_id ? 0 : parseInt(req.query.message_end_id);
    var count = req.query.count === undefined ? DEFAULT_PAGE_SIZE : parseInt(req.query.count);
    var closedInterval = (req.query.closed_interval != false && req.query.closed_interval === "true");

    if (contentType !== undefined && parseInt(contentType) === CONTENT_TYPES.Image) count = DEFAULT_PAGE_SIZE;

    if (req.query.message_start_id && req.query.message_end_id) count = 10000;

    if (!userId) {
        throw {httpStatus: 400, message: "Missing field: user_id."};
    }

    pmRepo.findAllMessages(userId, peerId, contentType === undefined ? "1,2,3,5,6" : contentType, msgStartId, msgEndId, count, closedInterval, function (err, rows) {
        if (err) {
            log.error("Get private message failed, ", err);

            res.status(500).send({message: "Get private messages failed."});
            return;
        }

        var messages = fillMessages(rows);

        // 清空统计信息
        statsRepo.clearPrivateChatSummary(userId, peerId, function (err, result) {
            if (err) console.log(err);
        });

        res.status(200).send(messages);
    });
});

/**
 * 获取未读私信。倒序排列。
 *
 * 参数：
 *  user_id 必须，医生ID
 *  peer_id 必须，对方医生ID
 *
 * 请求URL：
 *  /chats/pm/unread?user_id=sand&peer_id=Rose
 */
router.get(APIv1.Chats.PMUnread, function (req, res) {
    var userId = req.query.user_id;
    var peerId = req.query.peer_id;

    if (userId === undefined) {
        throw {httpStatus: 400, message: "Missing field: user_id."};
    }

    statsRepo.getPrivateChatSummary(userId, peerId, function (err, summary) {
        if (err) {
            log.error("Get unread private messages failed: ", err);

            res.status(500).send({message: "Get unread private messages failed."});
            return;
        }

        // 没有未读消息，直接返回
        if (summary.length == 0 || summary[0].new_msg_count === 0) {
            res.status(200).send({startId: 0, count: 0, records: []});
            return;
        }

        pmRepo.findUnread(peerId, userId, MAX_INT, summary[0].new_msg_count, function (err, rows) {
            if (err) {
                log.error("Get unread private messages failed: ", err);

                res.status(500).send({message: "Get unread private messages failed."});
                return;
            }

            var messages = fillMessages(rows);

            res.status(200).send(messages);
        });
    });
});

/**
 * 按时间倒序获取群消息。
 *
 * 参数：
 *  user_id 必须，医生ID
 *  group_id 必须，组ID
 *  message_start_id 可选，消息的起始ID，如果为空从最新的一条开始获取
 *  count 可选，消息数量，如果不指定、小于零或大于50，默认为50条
 *
 * 请求URL：
 *  /chats/gm?user_id=D2016008240002&group_id=494&content_type=2&message_start_id=0&message_end_id=0&count=20
 */
router.get(APIv1.Chats.GM, function (req, res) {
    var groupId = req.query.group_id;
    var userId = req.query.user_id;
    var contentType = req.query.content_type;
    var msgStartId = !req.query.message_start_id ? MAX_INT : parseInt(req.query.message_start_id);
    var msgEndId = !req.query.message_end_id ? 0 : parseInt(req.query.message_end_id);
    var count = req.query.count === undefined ? DEFAULT_PAGE_SIZE : parseInt(req.query.count);

    if (groupId === undefined) {
        throw {httpStatus: 400, message: "Missing field: group_id."};
    }

    if (contentType !== undefined && parseInt(contentType) === CONTENT_TYPES.Image) count = DEFAULT_PAGE_SIZE;

    if (req.query.message_start_id && req.query.message_end_id) count = 100000;

    gmRepo.findAllMessages(groupId, !contentType ? "1,2,3,5,6" : contentType, msgStartId, msgEndId, count, function (err, rows) {
        if (err) {
            console.log('Get group message failed: ', err);

            res.status(500).send({message: 'Get group message failed.'});
            return;
        }

        var messages = fillMessages(rows);

        // 清空统计信息
        statsRepo.clearGroupChatSummary(userId, groupId, function (err, result) {
            if (err) console.log(err);
        });

        res.status(200).send(messages);
    });
});

/**
 * 获取未读群消息。
 *
 * 请求URL:
 *  /chats/gm/unread?group_id=discussionGroupId&user_id=sand
 */
router.get(APIv1.Chats.GMUnread, function (req, res) {
    var userId = req.query.user_id;
    var groupId = req.query.group_id;

    if (userId === undefined) {
        throw {httpStatus: 400, message: "Missing field: user_id."};
    }

    if (groupId === undefined) {
        throw {httpStatus: 400, message: "Missing field: group_id."};
    }

    statsRepo.getGroupChatSummary(userId, groupId, function (err, summary) {
        if (err) {
            log.error("Get unread group messages failed: ", err);

            res.status(500).send({message: "Get unread group messages failed."});
            return;
        }

        var messages = {startId: 0, count: 0, records: []};
        if (summary.length == 0 || summary[0].new_msg_count === 0) {
            res.status(200).send(messages);
            return;
        }

        messages.count = summary[0].new_msg_count;
        gmRepo.findUnread(groupId, MAX_INT, messages.count, function (err, rows) {
            if (err) {
                log.error("Get unread group messages failed: ", err);

                res.status(500).send({message: "Get unread group messages failed."});
                return;
            }

            var messages = fillMessages(rows);

            res.status(200).send(messages);
        });
    });
});

/**
 * 将消息的返回结果合并成JSON。
 *
 * @param rows
 *
 * @returns {startId: 0, count: 0, records: []}
 */
function fillMessages(rows) {
    var messages = {startId: rows.length > 0 ? rows[0].msg_id : '', count: rows.length, records: []};
    for (var i = 0; i < rows.length; i++) {
        var row = rows[i];
        var record = {
            id: row.msg_id,
            from: row.from_uid,
            contentType: row.type,
            content: row.content,
            timestamp: objectUtil.timestampToLong(row.timestamp)
        };

        if (row.to_uid !== undefined) record.to = row.to_uid;
        if (row.at_uid !== undefined) record.at = row.at_uid;

        messages.records.push(record);
    }

    return messages;
}

//--------------------------------------------------------------//
//----------------------------消息统计----------------------------//
//--------------------------------------------------------------//

/**
 * 获取所有群组未读消息总数。
 *
 * 请求URL：
 *  /chats/gm/unread_count?user_id=sand
 *
 * 参数：
 *  user_id：医生ID
 */
router.get(APIv1.Chats.GMUnreadCount, function (req, res) {
    var userId = req.query.user_id;
    if (userId === null) {
        throw {httpStatus: 406, message: 'Missing fields.'};
    }

    statsRepo.getGroupChatAllUnReadCount(userId, function (err, result) {
        if (err) {
            console.log('Get all unread messages failed: ', err);

            res.status(500).send({message: 'Get all unread messages failed.'});
        }

        var data = {
            userId: userId,
            messageType: 2,
            newMessageCount: 0
        };

        if (result.length > 0) {
            for (var index = 0; index < result.length; index++) {
                data.newMessageCount += result[index].new_msg_count;
            }
        }

        res.send(data);
    });
});

/**
 * 获取特定群组消息统计情况。
 *
 * /chats/gm/statistic?group_id=GGG&&user_id=sand
 *
 * 参数：
 *  user_id：信息所有者id
 *  group_id：群组id
 */
router.get(APIv1.Chats.GMStats, function (req, res) {
    var userId = req.query.user_id;
    var groupId = req.query.group_id;
    if (userId === null || groupId === null) {
        throw {httpStatus: 406, message: 'Miss fields.'};
    }

    statsRepo.getGroupChatSummary(userId, groupId, function (err, result) {
        if (err) {
            console.log('Get group stats failed: ', err);

            res.status(500).send({message: 'Get group stats failed.'});
            return;
        }

        var data = {
            userId: userId,
            from: "",
            groupId: groupId,
            atMe: 0,
            lastContentType: 1,
            lastContent: "",
            newMessageCount: 0,
            timestamp: 0
        };

        if (result.length > 0) {
            var row = result[0];
            data.from = row.from_uid;
            data.groupId = row.gid;
            data.atMe = row.at_me;
            data.lastContentType = row.last_content_type;
            data.lastContent = row.lastContent;
            data.newMessageCount = row.new_msg_count;
            data.timestamp = objectUtil.timestampToLong(row.timestamp)
        }

        res.status(200).send(data);
    });
});

/**
 * 获取与某人的私信统计。
 *
 * /chats/pm/statistic?user_id=sand&&peer_id=rose
 *
 * 参数：
 *  user_id：信息所有者id
 *  peer_id：聊天对端id
 */
router.get(APIv1.Chats.PMStats, function (req, res) {
    var userId = req.query.user_id;
    var peerId = req.query.peer_id;
    if (userId == null || peerId == null) {
        throw {httpStatus: 406, message: "Missing fields."};
    }

    statsRepo.getPrivateChatSummary(userId, peerId, function (err, result) {
        if (err) {
            console.log("Get private messages stats failed: ", err);

            res.status(500).send({message: "Get private messages stats failed."});
        }

        var data = {
            userId: userId,
            peerId: peerId,
            lastCContentType: 1,
            lastContent: "",
            newMessageCount: 0,
            timestamp: 0
        };

        if (result.length > 0) {
            var row = result[0];

            data.userId = row.uid;
            data.peerId = row.from_uid;
            data.lastContentType = row.last_content_type;
            data.lastContent = row.last_content;
            data.newMessageCount = row.new_msg_count;
            data.timestamp = objectUtil.timestampToLong(row.timestamp)
        }

        res.status(0).send(data);
    });
});

/**
 * 获取所有未读私信总数。
 *
 * /chats/pm/unread_count?user_id=sand
 *
 * 参数：
 * uid：信息所有者id
 */
router.get(APIv1.Chats.PMUnreadCount, function (req, res) {
    var userId = req.query.user_id;

    statsRepo.getPrivateChatAllUnReadCount(userId, function (err, result) {
        if (err) {
            console.log("Get unread private message count failed: ", err);

            res.status(500).send({message: "Get unread private message count failed."});
        }

        var data = {userId: userId, messageType: 1, newMessageCount: 0};
        if (result.length > 0) {
            for (var i = 0; i < result.length; i++) {
                data.newMessageCount += result[i].new_msg_count;
            }
        }

        res.send(data);
    });
});

/**
 * 所有聊天消息未读数。
 *
 * 请求URL：
 *  /chats/chats/unread_count?user_id=sand
 *
 * 参数：
 *  user_id：信息所有者id
 */
router.get(APIv1.Chats.UnreadMsgCount, function (req, res) {
    var userId = req.query.user_id;
    if (userId === null) {
        throw {httpStatus: 406, message: "Missing fields."};
    }

    statsRepo.getChatAllUnReadCount(userId, function (err, result) {
        if (err) {
            console.error("Get all unread message count failed: ", err);

            res.status(500).send({message: "Get all unread message count failed."});
        }

        var data = {userId: userId, messageType: 0, newMessageCount: 0};
        if (result.length > 0) {
            for (var index = 0; index < result.length; index++) {
                data.newMessageCount += result[index].new_msg_count;
            }
        }

        res.send(data);
    });
});


/**
 * 搜索患者相关的数据，包括患者信息与相关的私信记录。关键词不支持空格拆分。
 *
 * 请求URL：
 *  /search/patient?user_id=3b723bb8699a11e69f7c005056850d66&user_role=1&keyword=庄
 *
 * 参数：
 *  keywords: 关键词
 */
router.get(APIv1.Chats.SearchAboutPatient, function (req, res) {
    var userId = req.query.user_id;
    var userRole = req.query.user_role;
    var keyword = req.query.keyword;

    if (!userId) throw {httpStatus: 406, message: "Missing fields: user_id."};
    if (!userRole) throw {httpStatus: 406, message: "Missing fields: user_role."};
    if (!keyword) throw {httpStatus: 406, message: "Missing fields: keyword."};

    searchRepo.searchPatients(userId, userRole, keyword, function (err, patients) {
        if (err) {
            log.error("Search patient on basic information failed: ", err);

            res.status(500).send({message: "Search patient on basic information failed."});
            return;
        }

        var data = {patients: [], chats: []};
        for (var i = 0; i < patients.length; ++i) {
            var patient = patients[i];
            data.patients.push({
                code: patient.code,
                name: patient.name,
                sex: patient.sex,
                birthday: objectUtil.timestampToLong(patient.birthday),
                avatar: patient.photo === null ? "" : patient.photo
            });
        }

        searchRepo.searchPatientPM(userId, keyword, function (err, chats) {
            if (err) {
                log.error("Search patient on private messages failed: ", err);

                res.status(500).send({message: "Search patient on private messages failed."});
                return;
            }

            var lastPatientCode = '';
            var lastPatient = {code: '', name: '', sex: '', avatar: '', messages: []};
            for (var i = 0; i < chats.length; ++i) {
                var chat = chats[i];
                if (lastPatientCode !== chat.code) {
                    lastPatientCode = chat.code;
                    lastPatient.code = chat.code;
                    lastPatient.name = chat.name;
                    lastPatient.sex = chat.sex;
                    lastPatient.birthday = objectUtil.timestampToLong(patient.birthday);
                    lastPatient.avatar = chat.photo === null ? "" : chat.photo;

                    data.chats.push(lastPatient);
                }

                lastPatient.messages.push({
                    id: chat.msg_id,
                    content: chat.content
                });
            }

            res.status(200).send(data);
        });
    });
});

/**
 * 搜索医生相关的数据，包括医生信息与相关的聊天记录，包括私信与群信。
 *
 * 请求URL：
 *  /search/doctor?user_id=5fa5e88f7a4111e69f7c005056850d66&keyword=丘
 *
 * 参数：
 *  keywords: 关键词
 */
router.get(APIv1.Chats.SearchAboutDoctor, function (req, res) {
    var userId = req.query.user_id;
    var keyword = req.query.keyword;

    if (!userId) throw {httpStatus: 406, message: "Missing fields: user_id."};
    if (!keyword) throw {httpStatus: 406, message: "Missing fields: keyword."};

    // 搜索医生
    searchRepo.searchDoctors(userId, keyword, function (err, doctors) {
        if (err) {
            log.error("Search doctor on basic information failed: ", err);

            res.status(500).send({message: "Search doctor on basic information failed."});
            return;
        }

        var data = {doctors: [], groups: [], chats: {doctors: [], groups: []}};
        for (var i = 0; i < doctors.length; ++i) {
            var doctor = doctors[i];
            data.doctors.push({
                code: doctor.code,
                name: doctor.name,
                sex: doctor.sex,
                avatar: doctor.photo === null ? "" : doctor.photo
            });
        }

        // 搜索讨论组名称及成员名称
        searchRepo.searchGroups(userId, keyword, function (err, groups) {
            if (err) {
                log.error("Search talk group failed: ", err);

                res.status(500).send({message: "Search talk group failed."});
                return;
            }

            var lastGroupCode = '';
            var lastGroup = null;
            for (var i = 0; i < groups.length; ++i) {
                var group = groups[i];
                if (lastGroupCode !== group.code) {
                    lastGroupCode = group.code;
                    lastGroup = {
                        code: group.code,
                        name: group.name,
                        type: GROUP_TYPE.DiscussionGroup,
                        members: []
                    };

                    data.groups.push(lastGroup);
                }

                lastGroup.members.push({
                    code: group.member_code,
                    name: group.member_name
                });
            }

            // 搜索医生间的私信
            searchRepo.searchDoctorMessages(userId, keyword, function (err, messages) {
                if (err) {
                    log.error("Search doctor private messages failed: ", err);

                    res.status(500).send({message: "Search doctor private messages failed."});
                    return;
                }

                var lastDoctor;
                var lastDoctorCode = '';
                for (var i = 0; i < messages.length; ++i) {
                    var message = messages[i];
                    if (lastDoctorCode !== message.code) {
                        lastDoctorCode = message.code;
                        lastDoctor = {
                            code: message.code,
                            name: message.name,
                            photo: message.photo === null ? "" : message.photo,
                            messages: []
                        };

                        data.chats.doctors.push(lastDoctor);
                    }

                    lastDoctor.messages.push({
                        id: message.msg_id,
                        content: message.content
                    });
                }

                // 搜索医生间的讨论组消息
                searchRepo.searchGroupMessages(userId, keyword, function (err, messages) {
                    if (err) {
                        log.error("Search doctor group messages failed: ", err);

                        res.status(500).send({message: "Search doctor group messages failed."});
                        return;
                    }

                    // g.code, g.name, gm.msg_id, gm.content
                    var lastGroup;
                    var lastGroupCode = '';
                    for (var i = 0; i < messages.length; ++i) {
                        var message = messages[i];
                        if (lastGroupCode !== message.code) {
                            lastGroupCode = message.code;
                            lastGroup = {
                                code: message.code,
                                name: message.name,
                                messages: []
                            }

                            data.chats.groups.push(lastGroup);
                        }

                        lastGroup.messages.push({
                            id: message.msg_id,
                            content: message.content
                        });
                    }

                    res.status(200).send(data);
                });
            });
        });
    });
});

/**
 * 判断当前会话是否已经结束。
 *
 * 请求URL：
 *  /chats/pm/finished?user_id=sand&peer_id=rose
 */
router.get(APIv1.Chats.PMFinished, function (req, res) {
    var userId = req.query.user_id;
    var peerId = req.query.peer_id;
    if(!userId){
        throw {httpStatus: 406, message: "Missing field: user_id"};
    }

    if(!peerId){
        throw {httpStatus: 406, message: "Missing field: peer_id"};
    }

    pmRepo.isCurrentSessionFinished(userId, peerId, function (err, result) {
        if(err){
            log.error("Get session finish status failed: ", err);

            throw {httpStatus: 500, message: "Get session finish status failed."};
        }

        var data = {finished: true, consultId: ''};
        if(result.length > 0){
            var finishRow = result[0];

            data.finished = finishRow.finished === 1;
            if(!data.finished){
                data.consultId = finishRow.consult_id;
            }
        }

        res.status(200).send(data);
    })
});

module.exports = router;
