const Message = require('./message.js').Message
    ,MeMessage = require('./message.js').MeMessage
    ,NoticeMessage = require('./message.js').NoticeMessage
    ,RoomHistory = require('./message.js').RoomHistory;

/**
 * @constructor
 * @extends {RoomHistory}
 * @param {Room|string} room or roomId
 * @param {number} keepMessages number of messages to keep in memory
 * @param {Array|undefined} evts
 * @param {number|undefined} now
**/
function SlackHistory(room, keepMessages, evts, now) {
    RoomHistory.call(this, room, keepMessages, evts, now);
}
SlackHistory.prototype = Object.create(RoomHistory.prototype);
SlackHistory.prototype.constructor = SlackHistory;

SlackHistory.prototype.messageFactory = function(ev, ts) {
    if (ev["is_ephemeral"] === true)
        return new NoticeMessage(ev, ts);
    if (ev["subtype"] === "me_message")
        return new MeMessage(ev, ts);
    return new Message(ev, ts);
}

/**
 * @return {number} ts
**/
SlackHistory.prototype.push = function(ev, t) {
    var msg;
    if (!ev["type"] || ev["type"] === "message") {
        var exists = false
            ,targetId = ev["ts"]
            ,modifArg = ev;

        if (ev["subtype"] === "message_changed" && ev["previous_message"]) {
            targetId = ev["previous_message"]["ts"];
            modifArg = ev["message"]
        } else if (ev["subtype"] === "message_deleted" && ev["previous_message"]) {
            targetId = ev["previous_message"]["ts"];
            modifArg = null;
        }
        for (var i =0, nbMsg = this.messages.length; i < nbMsg; i++) {
            msg = this.messages[i];
            if (msg.id === targetId) {
                msg.update(modifArg, t);
                exists = true;
                break;
            }
        }
        if (!exists) {
            msg = this.messageFactory(ev, t);
            this.messages.push(msg);
        }
    } else if (ev["type"] === "reaction_added") {
        msg = this.addReaction(ev["reaction"], ev["user"], ev["item"]["ts"], t);
    } else if (ev["type"] === "reaction_removed") {
        msg = this.removeReaction(ev["reaction"], ev["user"], ev["item"]["ts"], t);
    } else {
        return 0;
    }
    while (this.messages.length > this.keepMessages)
        this.messages.shift();
    return msg ? msg.ts : 0;
}

SlackHistory.prototype.lastMessage = function() {
    return this.messages[this.messages.length -1];
}

/**
 * @param {string} reaction
 * @param {string} userId
 * @param {string} msgId
 * @param {number} ts
 * @return {SlackMessage|null}
**/
SlackHistory.prototype.addReaction = function(reaction, userId, msgId, ts) {
    var msg = this.getMessageById(msgId);
    if (msg)
        msg.addReaction(reaction, userId, ts);
    return msg;
}

/**
 * @param {string} reaction
 * @param {string} userId
 * @param {string} msgId
 * @param {number} ts
 * @return {SlackMessage|null}
**/
SlackHistory.prototype.removeReaction = function(reaction, userId, msgId, ts) {
    var msg = this.getMessageById(msgId);
    if (msg)
        msg.removeReaction(reaction, userId, ts);
    return msg;
}

/**
 * @param {number} ts
 * @return {SlackMessage|null}
**/
SlackHistory.prototype.getMessage = function(ts) {
    for (var i =0, nbMessages = this.messages.length; i < nbMessages && ts >= this.messages[i].ts; i++) {
        if (this.messages[i].ts === ts)
            return this.messages[i];
    }
    return null;
}

/**
 * @param {string} id
 * @return {SlackMessage|null}
**/
SlackHistory.prototype.getMessageById = function(id) {
    for (var i =0, nbMessages = this.messages.length; i < nbMessages; i++) {
        if (this.messages[i].id == id)
            return this.messages[i];
    }
    return null;
}

/**
 * @return {Array.<*>}
**/
SlackHistory.prototype.toStatic = function(knownVersion) {
    var result = [];

    for (var i = this.messages.length -1; i >= 0; i--) {
        if (this.messages[i].version > knownVersion)
            result.push(this.messages[i].toStatic());
    }
    return result;
}

SlackHistory.prototype.resort = function() {
    this.messages.sort(function(a, b) {
        return a.ts -b.ts;
    });
};

module.exports.SlackHistory = SlackHistory;

