#include "Server.hpp"
#include "errcodes.hpp"
#include <algorithm>

int
Server::_cmdJOIN(Message const& msg)
{
    static std::string const charCheck(" \a\r\n");

    if (int rv = msg.expectArgs(1)) {
        return rv == -1 ? rv : 0;
    }

    Client& client = msg.getClient();

    string_vector const& chansToJoin = split(msg.getArgs()[0], ",", true);
    string_vector keywords(chansToJoin.size());
    if (msg.getArgs().size() > 1) {
        keywords = split(msg.getArgs()[1], ",", false);
    }

    for (size_t i = 0; i < chansToJoin.size(); ++i) {
        if (chansToJoin[i][0] != '&' && chansToJoin[i][0] != '#') {
            if (client.sendCode(ERR_NOSUCHCHANNEL, chansToJoin[i], "No such channel")) {
                return 1;
            }
            continue;
        }
        for (size_t j = 1; j < chansToJoin[i].length(); ++j) {
            if (charCheck.find(chansToJoin[i][j]) != charCheck.npos) {
                if (client.sendCode(ERR_NOSUCHCHANNEL, chansToJoin[i], "No such channel")) {
                    return 1;
                }
                goto loop_skip;
            }
        }
        {
            std::vector<Channel>::iterator it = std::find(_channels.begin(),
                                            _channels.end(), chansToJoin[i]);
            if (it == _channels.end()) {
                it = _channels.insert(_channels.end(), Channel(chansToJoin[i], client));
                if (it->isChannelEmpty()) {
                    _channels.erase(it);
                }
            } else if (it->getUserLimit() && it->getUserLimit() >= it->numClients()) {
                if (client.sendCode(ERR_CHANNELISFULL, chansToJoin[i], "Cannot join channel (+l)")) {
                    return 1;
                }
                goto loop_skip;
            } else if (it->isInviteOnly() && !client.isInvited(*it)) {
                if (client.sendCode(ERR_INVITEONLYCHAN, chansToJoin[i], "Cannot join channel (+i)")) {
                    return 1;
                }
            } else if (!it->getKeyword().empty() && keywords[i] != it->getKeyword()) {
                if (client.sendCode(ERR_BADCHANNELKEY, chansToJoin[i], "Cannot join channel (+k)")) {
                    return 1;
                }
            } else {
                it->addClient(client);
            }
        }
loop_skip:;
    }
    return 0;
}
