var accountInfo = {};

var eventStreamInfo = {
    from: "END"
};

var roomInfo = [];
var memberInfo = [];
var viewingRoomId;

// ************** Event Streaming **************
var longpollEventStream = function() {
    var url = "http://localhost:8008/_matrix/client/api/v1/events?access_token=$token&from=$from";
    url = url.replace("$token", accountInfo.access_token);
    url = url.replace("$from", eventStreamInfo.from);

    $.getJSON(url, function(data) {
        eventStreamInfo.from = data.end;
        
        var hasNewLatestMessage = false;
        var updatedMemberList = false;
        var i=0;
        var j=0;
        for (i=0; i<data.chunk.length; ++i) {
            if (data.chunk[i].type === "m.room.message") {
                console.log("Got new message: " + JSON.stringify(data.chunk[i]));
                if (viewingRoomId === data.chunk[i].room_id) {
                    addMessage(data.chunk[i]);
                }
                
                for (j=0; j<roomInfo.length; ++j) {
                    if (roomInfo[j].room_id === data.chunk[i].room_id) {
                        roomInfo[j].latest_message = data.chunk[i].content.body;
                        hasNewLatestMessage = true;
                    }
                }
            }
            else if (data.chunk[i].type === "m.room.member") {
                if (viewingRoomId === data.chunk[i].room_id) {
                    console.log("Got new member: " + JSON.stringify(data.chunk[i]));
                    addMessage(data.chunk[i]);
                    for (j=0; j<memberInfo.length; ++j) {
                        if (memberInfo[j].state_key === data.chunk[i].state_key) {
                            memberInfo[j] = data.chunk[i];
                            updatedMemberList = true;
                            break;
                        }
                    }
                    if (!updatedMemberList) {
                        memberInfo.push(data.chunk[i]);  
                        updatedMemberList = true;
                    }
                }
                if (data.chunk[i].state_key === accountInfo.user_id) {
                    getCurrentRoomList(); // update our join/invite list
                }
            }
            else {
                console.log("Discarding: " + JSON.stringify(data.chunk[i]));
            }
        }
        
        if (hasNewLatestMessage) {
           setRooms(roomInfo);
        }
        if (updatedMemberList) {
            $("#members").empty();
            for (i=0; i<memberInfo.length; ++i) { 
                addMember(memberInfo[i]);
            }
        }
        longpollEventStream();
    }).fail(function(err) {
        setTimeout(longpollEventStream, 5000);
    });
};

// ************** Registration and Login **************
var onLoggedIn = function(data) {
    accountInfo = data;
    longpollEventStream();
    getCurrentRoomList();
    $(".roomListDashboard").css({visibility: "visible"});
    $(".roomContents").css({visibility: "visible"});
    $(".signUp").css({display: "none"});
};

$('.login').live('click', function() {
    var user = $("#userLogin").val();
    var password = $("#passwordLogin").val();
    $.ajax({
        url: "http://localhost:8008/_matrix/client/api/v1/login",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify({ user: user, password: password, type: "m.login.password" }),
        dataType: "json",
        success: function(data) {
            onLoggedIn(data);
        },
        error: function(err) {
            alert("Unable to login: is the home server running?");  
        }
    }); 
});

$('.register').live('click', function() {
    var user = $("#userReg").val();
    var password = $("#passwordReg").val();
    $.ajax({
        url: "http://localhost:8008/_matrix/client/api/v1/register",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify({ user_id: user, password: password }),
        dataType: "json",
        success: function(data) {
            onLoggedIn(data);
        },
        error: function(err) {
            var msg = "Is the home server running?";
            var errJson = $.parseJSON(err.responseText);
            if (errJson !== null) {
                msg = errJson.error;   
            }
            alert("Unable to register: "+msg);  
        }
    });
});

// ************** Creating a room ******************
$('.createRoom').live('click', function() {
    var roomAlias = $("#roomAlias").val();
    var data = {};
    if (roomAlias.length > 0) {
        data.room_alias_name = roomAlias;   
    }
    $.ajax({
        url: "http://localhost:8008/_matrix/client/api/v1/createRoom?access_token="+accountInfo.access_token,
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
        dataType: "json",
        success: function(response) {
            $("#roomAlias").val("");
            response.membership = "join"; // you are automatically joined into every room you make.
            response.latest_message = "";
            
            roomInfo.push(response);
            setRooms(roomInfo);
        },
        error: function(err) {
            alert(JSON.stringify($.parseJSON(err.responseText)));  
        }
    }); 
});

// ************** Getting current state **************
var getCurrentRoomList = function() {
    var url = "http://localhost:8008/_matrix/client/api/v1/initialSync?access_token=" + accountInfo.access_token + "&limit=1";
    $.getJSON(url, function(data) {
        var rooms = data.rooms;
        for (var i=0; i<rooms.length; ++i) {
            if ("messages" in rooms[i]) {
                rooms[i].latest_message = rooms[i].messages.chunk[0].content.body;   
            }
        }
        roomInfo = rooms;
        setRooms(roomInfo);  
    }).fail(function(err) {
        alert(JSON.stringify($.parseJSON(err.responseText)));
    });
};

var loadRoomContent = function(roomId) {
    console.log("loadRoomContent " + roomId);
    viewingRoomId = roomId;
    $("#roomName").text("Room: "+roomId);
    $(".sendMessageForm").css({visibility: "visible"});
    getMessages(roomId);
    getMemberList(roomId);
};

var getMessages = function(roomId) {
    $("#messages").empty();
    var url = "http://localhost:8008/_matrix/client/api/v1/rooms/" + 
              encodeURIComponent(roomId) + "/messages?access_token=" + accountInfo.access_token + "&from=END&dir=b&limit=10";
    $.getJSON(url, function(data) {
        for (var i=data.chunk.length-1; i>=0; --i) {
            addMessage(data.chunk[i]);   
        }
    });
};

var getMemberList = function(roomId) {
    $("#members").empty();
    memberInfo = [];
    var url = "http://localhost:8008/_matrix/client/api/v1/rooms/" + 
              encodeURIComponent(roomId) + "/members?access_token=" + accountInfo.access_token;
    $.getJSON(url, function(data) {
        for (var i=0; i<data.chunk.length; ++i) {
            memberInfo.push(data.chunk[i]);
            addMember(data.chunk[i]);   
        }
    });
};

// ************** Sending messages **************
$('.sendMessage').live('click', function() {
    if (viewingRoomId === undefined) {
        alert("There is no room to send a message to!");
        return;
    }
    var body = $("#body").val();
    sendMessage(viewingRoomId, body);
});

var sendMessage = function(roomId, body) {
    var msgId = $.now();
    
    var url = "http://localhost:8008/_matrix/client/api/v1/rooms/$roomid/send/m.room.message?access_token=$token";
    url = url.replace("$token", accountInfo.access_token);
    url = url.replace("$roomid", encodeURIComponent(roomId));
    
    var data = {
        msgtype: "m.text",
        body: body
    };
    
    $.ajax({
        url: url,
        type: "POST",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),
        dataType: "json",
        success: function(data) {
            $("#body").val("");
        },
        error: function(err) {
            alert(JSON.stringify($.parseJSON(err.responseText)));  
        }
    });
};

// ************** Navigation and DOM manipulation **************
var setRooms = function(roomList) {
    // wipe existing entries
    $("#rooms").find("tr:gt(0)").remove();
    
    var rows = "";
    for (var i=0; i<roomList.length; ++i) {
        row = "<tr>" +
              "<td>"+roomList[i].room_id+"</td>" +
              "<td>"+roomList[i].membership+"</td>" +
              "<td>"+roomList[i].latest_message+"</td>" +
              "</tr>";  
        rows += row;
    }
    
    $("#rooms").append(rows);
    
    $('#rooms').find("tr").click(function(){
        var roomId = $(this).find('td:eq(0)').text();
        var membership = $(this).find('td:eq(1)').text();
        if (membership !== "join") {
            console.log("Joining room " + roomId); 
            var url = "http://localhost:8008/_matrix/client/api/v1/rooms/$roomid/join?access_token=$token";
            url = url.replace("$token", accountInfo.access_token);
            url = url.replace("$roomid", encodeURIComponent(roomId));
            $.ajax({
                url: url,
                type: "POST",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify({membership: "join"}),
                dataType: "json",
                success: function(data) {
                    loadRoomContent(roomId);
                    getCurrentRoomList();
                },
                error: function(err) {
                    alert(JSON.stringify($.parseJSON(err.responseText)));  
                }
            });
        }
        else {
            loadRoomContent(roomId);
        }
    });
};

var addMessage = function(data) {

    var msg = data.content.body;
    if (data.type === "m.room.member") {
        if (data.content.membership === undefined) {
            return;
        }
        if (data.content.membership === "invite") {
            msg = "<em>invited " + data.state_key + " to the room</em>";
        }
        else if (data.content.membership === "join") {
            msg = "<em>joined the room</em>";
        }
        else if (data.content.membership === "leave") {
            msg = "<em>left the room</em>";
        }
        else if (data.content.membership === "ban") {
            msg = "<em>was banned from the room</em>";
        }
    }
    if (msg === undefined) {
        return;
    }

    var row = "<tr>" +
              "<td>"+data.user_id+"</td>" +
              "<td>"+msg+"</td>" +
              "</tr>"; 
    $("#messages").append(row);
};

var addMember = function(data) {
    var row = "<tr>" +
              "<td>"+data.state_key+"</td>" +
              "<td>"+data.content.membership+"</td>" +
              "</tr>"; 
    $("#members").append(row);
};