/**
 * 医生模型。
 */
"use strict";

var EventEmitter = require('events').EventEmitter;
var util = require('util');

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

var userRepo = require('../repository/doctor.repo.js');
var gmRepo = require('../repository/group.msg.repo');
var pmRepo = require('../repository/private.msg.repo');
var nmRepo = require("../repository/notify.msg.repo");
var statsRepo = require("../repository/stats.msg.repo");
var objectUtil = require("../util/objectUtil.js");

var MODEL_EVENTS = require('../include/commons').MODEL_EVENTS;
var CONTENT_TYPES = require('../include/commons').CONTENT_TYPE;
var PLATFORMS = require('../include/commons').PLATFORM;

function Doctor(){
    EventEmitter.call(this);
}

/**
 * 向医生发送消息。
 *
 * @param message
 */
Doctor.prototype.sendMessage = function(message){
    var self = this;
    userRepo.isExist(message.to, function (err, rows) {
        if (err) {
            modelUtil.emitDbError(self, 'Lookup receiving users failed', err);
            return;
        }

        if (rows.length == 0) {
            self.emit(MODEL_EVENTS.DataNotFound, {});
            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) {
                modelUtil.emitDbError(self, 'Save private message failed.', err);
                return;
            }

            // 返回发送成功后的消息记录，控制器可选择结束网络连接
            pmRepo.findOneMessage(result.insertId, function (err, msg) {
                if (err) {
                    modelUtil.emitDbError(self, 'Save private message success, but return last message failed.', err);
                } else {
                    self.emit(MODEL_EVENTS.OK, fillMessages(msg));
                }
            });

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

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

            // 获取对方状态，即对端的系统平台，token等信息，并推送通知消息给对端
            userRepo.getUserStatus(message.to, function (err, result) {
                if (err) {
                    modelUtil.logDbError('Get target user status for private message failed： ' + message.to, err);
                    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 isOnline = false;
                var target;
                if (result.length > 0) {
                    target = result[0];
                    if (target.is_online) {
                        isOnline = true;
                    }
                }

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

                // 保存通知消息到数据库中并根据用户在线状态推送此消息
                nmRepo.save(message.to, message.contentType, title, content, notifyMessage, isOnline, function (err, result) {
                    if (err) {
                        log.error('Save private notify message failed, ', err);
                    } else {
                        if (isOnline === 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);
                                        }
                                    });
                            }
                        }
                    }
                });
            });
        });
    });
};

/**
 * 获取最近聊天的用户，组。
 */
Doctor.prototype.getRecentChats = function(){
    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);
    });
};

/**
 * 获取参与的聊天列表，包括：点对点，参与的讨论组，系统消息等。
 *
 * @param userId
 */
Doctor.prototype.getChatList = function (userId) {
    var self = this;

    // 与患者的私信
    pmRepo.findAllP2PWithPatient(userId, function (err, patients) {
        if (err) {
            modelUtil.emitDbError(self, 'Get chat list with patient failed', err);
            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) {
                modelUtil.emitDbError(self, 'Get group list with patient failed', err);
                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) {
                    modelUtil.emitDbError(self, 'Get chat list with doctor failed', err);
                    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) {
                        modelUtil.emitDbError(self, 'Get group list with doctor failed', err);
                        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)
                        });
                    }

                    self.emit(MODEL_EVENTS.OK, chats);
                });
            });
        })
    });
};

/**
 * 获取与医生的聊天列表，包括：点对点，参与的讨论组。
 *
 * @param userId
 */
Doctor.prototype.getChatListWithDoctor = function(userId){
    // 先获取医生间的私聊
    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);
        });
    });
};

/**
 * 获取与指定用户的聊天记录。
 *
 * @param userId
 * @param peerId
 */
Doctor.prototype.getPrivateMessages = function(userId, peerId){
    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);
    });
};

/**
 * 获取与指定用户的未读聊天记录。
 *
 * @param userId
 * @param peerId
 */
Doctor.prototype.getUnreadPrivateMessages = function (userId, peerId) {
    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);
        });
    });
};

/**
 * 将消息的返回结果合并成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;
}

// This class inherits from EventEmitter and expose class
util.inherits(Doctor, EventEmitter);
module.exports = Doctor;