var $ = jQuery;
const getElement = (id) => document.getElementById(id);
const ws = new WebSocket('ws://bwc.ryanpandya.com/socket');
var username = "unnamed";
var pId = 0;
var cards = [];
var lastCard = false;
var players = [];
var gameMode = "draw";
const timeFormat = 'h:mm a [PDT]';
const notification_pos = "top-right";

function range(size, startAt = 0) {
    return [...Array(size).keys()].map(i => i + startAt);
}

function heartbeat() {
    clearTimeout(this.pingTimeout);
    console.log("Ping");
    this.pingTimeout = setTimeout(() => {
	this.terminate();
    }, 30000 + 1000);
}

ws.onopen = (moot) => {
    heartbeat;
    var urlParams = new URLSearchParams(window.location.search);
    console.log('Connected to websocket.');
    username = urlParams.get('username');
    UIkit.notification({
	message: 'Connected!',
	status: 'success',
	pos: notification_pos,
	timeout: 1000
    });
    if(username == null || username == ""){
	window.location = "/";
    }    
    else{
	
    }
    
};

const addMessage = (e) => {
    var self_marker = "";
    if(e.pId == pId){
	self_marker = "self";
    }
    $("ul#chatbox").append(
	'<li class="message uk-margin-top">\
                <p class="uk-text-muted uk-text-small uk-margin-small">\
                  <span class="uk-float-right uk-margin-right">'+e.timestamp+'</span>\
                  <span class="uk-text-primary uk-text-bold username '+self_marker+'" pId='+e.pId+'>'+e.username+'</span>\
                <p style="font-size:12px;">'+e.message+'</p>\
                </p>\
              </li>'
    );
}

const addUser = (newPlayer) => {
    var picker = "";
    var existing = false;
    players.forEach(function(p){ // Check if we already know about this player (is this a reconnection attempt)
	if(p.pId == newPlayer.pId){ // Looks like it is
	    existing = true; console.log("Hit on " + newPlayer.username); // Make note	    
	}
    });
    
    if(existing){
	// What to do if this is a duplicate
	
    }else{
	// Otherwise
	notice(newPlayer.username + " has joined the game.");
	players.push(newPlayer);
	if(newPlayer.username == username){ // This user is actually us, so make the username editable
	    picker = '<div class="uk-overlay uk-position-center"><span class="change-profile uk-icon uk-overlay-icon" uk-overlay-icon="icon: camera"  uk-toggle="target: #profileModal"></span></div>';
	    u = '<input class="uk-form-blank uk-text-primary play-mode-username input-username" onKeyUp="javascript:playModeChangeUsername();" id="username" value="'+username+'">';
	}
	else{ // Otherwise just display the username
	    u = newPlayer.username;
	}
	
	var el = '\
<li class="player" data-pId="'+newPlayer.pId+'"><div class="uk-inline"><img data-pId="'+newPlayer.pId+'" class="uk-border-circle player" src="'+newPlayer.profilepic+'" alt="" width="100" height="100">'+picker+'</div><div class="player-username">'+u+'</div></li>';
	
	$("ul.players-list").append(el);
	$("span#number-of-players").text(parseInt($("span#number-of-players").text())+1); // This is probably wrong and will cause duplicates        
	

	
    }
    
}

const delUser = (username) => {

}

const changeMode = (data) => {
    $("#pick-first-turn").css({'display':'flex'});    
    $("#card-view").hide();
    $(".active-card-controls").hide();

    if(data.playerTurn.pId == pId){
	notice("The game has started. Your move!");
    }
    else{
	notice("The game has started. Move: " + data.playerTurn.username);
    }
    gameMode = data.mode;
    changeActivePlayer(data.playerTurn, data.incompleteCard);
}

const decrementCardsCount = () => {
    var el = $("#toggle_play > .uk-badge");
    var newNumber = parseInt(el.text()) - 1;
    console.log(newNumber);
    if(newNumber < 2){
	el.text("last card").css({'background':'maroon',color:'white'});
    }
    if(newNumber == 0 || newNumber == NaN){
	el.text("out of cards").css({'background':'black',color:'white'});
    }    
    else{
	el.html(newNumber + "&nbsp;cards").css({'background':'#eee',color:'#666'});;
    }    
};

const changeActivePlayer = (player, card) => {
    clearActiveCard();
    if(player.pId == pId){
	// Our turn!
	$(".active-card-controls").css({'display':'flex'});
	if(card){
	    console.log("There's a card in memory already.");
	    pullCard(card);
	}
	else{
	    console.log("Requesting a card from the server...");
	    request = {
		'type': 'pullCard',
		'player': player
	    }
	    decrementCardsCount();
	    ws.send(JSON.stringify(request));
	}
	$("#game-status").text("your turn").css({'background':'palegoldenrod','color':'#666'}).fadeIn();
    }
    else{
    	$("#game-status").text(player.username+"'s turn").fadeIn();
	$(".turn-indicator").css({"display":"inherit"});
	if(!card){
	    decrementCardsCount();
	}
	else{
	    if(card.revealed){
		$(".revealed-card-notice").show();
		pullCard(card);
	    }
	}
    }
    $("b.currentPlayer").text(player.username);
    $("li.current-player").removeClass("current-player");
    $("li[data-pId="+player.pId+"]").addClass("current-player");
    
}

const revealCard = () => {
    card.revealed = true;
    packet = {
	'type': 'revealCard',
	'card': card
    }
    markRevealedCard();
    ws.send(JSON.stringify(packet));
}
const clearActiveCard = () => {
    var empty = "";
    $(".active-card").hide().attr('data-author',empty);
    $("#pick-first-turn").css({'display':'flex'});
    $(".revealed-card-notice").hide();
    $(".active-card-controls").hide();
    $(".active-card h1.card-title").text(empty);
    $(".active-card img.card-picture").attr('src',empty);
    $(".active-card div.card-content").text(empty);
    $("li.reveal-card > a").text("Reveal Card").removeClass('uk-disabled').removeClass('revealed');    
}
const doneWithCard = () => {
    clearActiveCard();    
    $("#game-status").css({"background":"#1e87f0","color":"#fff"});
    packet = {
	'type': 'endTurn'
    }    
    ws.send(JSON.stringify(packet));
}

const addVote = (i) => {
    var el = $(".play-list-vote[data-pId="+i+"]");
    el.text(parseInt(el.text()) + 1).css({"display":"grid", "float":"right"});
}

const pullCard = (pulledCard) => {
    card = pulledCard;

    const cardAuthor = pulledCard.author;
    const cardTitle = pulledCard.title;
    const cardImage = pulledCard.image;
    const cardContent = pulledCard.content;
   
    $(".active-card").attr('data-author',cardAuthor);
    $(".active-card h1.card-title").text(cardTitle); if(cardTitle == ""){$(".active-card h1.card-title").hide()}
    $(".active-card img.card-picture").attr('src',cardImage);
    $(".active-card div.card-content").text(cardContent);

    if(cardAuthor == username){
	$(".your-card").show();	
    }
    
    $("#pick-first-turn").hide();
    $("#card-view").css({'display':'flex'});
    if(card.revealed){
	markRevealedCard();
    }   
}

const markRevealedCard = () => {
    $("li.reveal-card > a").text("revealed").addClass('uk-disabled revealed');
}

const viewRevealedCard = (card) => {
    pullCard(card);
    if($("b.currentPlayer").first().text() != username){$(".revealed-card-notice").show()};
}

const updateUsername = (i, uname) => {
    $(".input-username").val(uname);
    const url = window.location.origin + window.location.pathname;
    $("span.username[pId='"+i+"']").text(uname);
    $(".input-username").val(uname);
    history.pushState({},
		      "rename",
		      url + "?username=" + uname
		     );
}

ws.onmessage = (event) => {
    event = JSON.parse(event.data); 
    switch(event.type){
    case 'init':
	if(event.mode == "error"){
	    window.location = window.origin + "?error=username";
	}
	console.log(">> Initializing game...");
	pId = event.id;
	console.log("You are in the game as '" + username + "' (Player " + pId + ").");
	$(".input-username").val(username);
	event.players.forEach(function(p){
	    addUser(p);
	});
	$("#toggle_play > .uk-badge").text(event.cards+1 +" cards");
	decrementCardsCount();
	if(event.mode == "play"){
	    changeMode(event);
	    $("#toggle_play").click();
	}
	$(".input-username").value = username;
	$("span#number-of-players").text(event.players.length);
    	event.messages.forEach(function(e){
	    addMessage(e);
	});
	break;
    case 'changeMode':
	changeMode(event);
	addMessage(event.message);
	break;
    case 'changeUsername':
	console.log('Got an updated username: Player %s is now "%s".', event.pId, event.username);
	updateUsername(event.pId, event.username);
	break;
    case 'updateCardsList':
	if(username == event.author){
	    notice("Your card was submitted.");
	}else{
	    notice(event.author + " submitted a card.");
	}
	var el = $("#toggle_play > .uk-badge");
	el.html(parseInt(el.text()) + 1 +"&nbsp;cards");
	break;
    case 'error':
	console.log(">> Error: " + event.content);
	if(event.err_username){
	    
	}
	UIkit.notification({
	    message: event.content,
	    status: 'warning',
	    pos: notification_pos,
	    timeout: 1000
	});
	break;
    case 'notification':
	console.log(">> Notification: " + event.content);
	UIkit.notification({
	    message: event.content,
	    status: 'success',
	    pos: notification_pos,
	    timeout: 1000
	});
	break;
    case 'gameOver':
	console.log(">> GAME OVER: " + event.content);
	UIkit.notification({
	    message: event.content,
	    status: 'success',
	    pos: notification_pos,
	    timeout: 1000
	});
	$("#game-status").html("game over");
	$("#play_mode").html(
	    "<h1>Game over, thanks for playing!</h1>"
	);
	break;
    case 'message':
	console.log(">> Got a message.");	
	addMessage(event);
	break;
    case 'changeProfilePic':
	updateProfPic(event.player, event.href);
	break;
    case 'vote':
	addVote(event.pId);	
	if(firstPlayerPicked){
	    notice("First turn starting!");
	    $("#draw_mode").html("");
	}
	break;
    case 'revealCard':
	viewRevealedCard(event.card);
	break;
    case 'pulledCard':
	if(event.last){
	    notice("Last card!");
	    lastCard = true;
	}
	pullCard(event.card);
	break;
    case 'nextTurn':
	changeActivePlayer(event.playerTurn, null);
	break;
    case 'newPlayer':
	var player = event.player;
	if(player.pId != pId){
	    addUser(player);
	}
	break;
    default:
	console.log('Unknown event. Pasting:');
	console.log(event);
    }
    
};

const changeUsername = (name) => {
    packet = {
	"type": "changeUsername",
	"pId": pId,
	"username": name
    }
    console.log("Changing username to: '"+name+"'");
    username = name;
    ws.send(JSON.stringify(packet));    
};

const notice = (message) => {
UIkit.notification({
	message: message,
	status: 'primary',
	pos: notification_pos,
	timeout: 2000
    });    
}
    
const error = (message) => {
    UIkit.notification({
	message: message,
	status: 'danger',
	pos: notification_pos,
	timeout: 2000
    });    
}

const urlify = (text) => {
    var urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
    //var urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url,b,c) {
	var url2 = (c == 'www.') ?  'http://' +url : url;
	return '<a href="' +url2+ '" target="_blank">' + url + '</a>';
    }) 
};

const submitMessage = () => {
    message = $("#message").val();
    if(message.trim()){
	const timestamp = new Date();
	packet = {
	    "type": "message",
	    "pId": pId,
	    "username": username,
	    "message": urlify(message.trim()),
	    "timestamp": new Date()
	}
	console.log("Sending message.");
	ws.send(JSON.stringify(packet));
	$("#message").val("");
    }};

const chooseGiphy = (url) => {
    $("img.card-picture").attr("src", url);
    $(".uk-close").click();
}

const chooseProfile = (url) => {
    packet = {
	'type': 'changeProfilePic',
	'player': {
	    'pId': pId,
	    'username': username
	},
	'href': url
    }
    $(".change-profile > svg").hide();
    $(".uk-close").click();    
    ws.send(JSON.stringify(packet));
}

const updateProfPic = (player, url) => {
    $("img[data-pId="+player.pId+"]").attr('src',url);
}

const giphySearch = () => {
    var query = $("#giphySearch").val().trim().replace(/ /g, "+");
    const api_url = "https://api.giphy.com/v1/gifs/search?api_key=GUHvLYHRcNgPAIKt4PNZcjYw5FBeBX0F&q="+query+"&limit=25&offset=0&rating=R&lang=en";
    $.ajax({url: api_url, method: 'GET'}).done(function(response){
	
	// This is the API response data. It's a JSON object of 25 gifs
	console.log(response.data);
	$("#giphySearchResults").html("");
	response.data.forEach(function(i){
	    var giphyURL = i.images.fixed_height.url;
	    $("#giphySearchResults").append(
		"<a href='javascript:chooseGiphy("
		    + '"'
		    + giphyURL
		    + '"'
		    +");'><img class='search-result' src='"+giphyURL+"'/></a>"
	    );
	});
	
    });    
};

const voteForPlayer = (i) => {
    console.log("Sending in a vote.");
    packet = {
	'type': "vote",
	'pId': i	
    }

    ws.send(JSON.stringify(packet));
}

const playModeChangeUsername = (e) => {
    if(e.keyCode === 13){
	changeUsername($(".player-username > input").val());
    };    
}

$().ready(function() {
    $("#toggle_chat").on('click', function(e){
	$(this).closest("li").toggleClass("uk-active");
    });

    $(".input-username").keydown(function(e){
	if(e.keyCode === 13){
	    changeUsername(this.value);
	};    
    });
    $(".input-username").focusout(function(e){
	changeUsername(this.value);
    });
    $("#message").keyup(function(e){
	if(e.keyCode === 13){
	    submitMessage();
	};
    });
    $("a#toggle_draw").on('click', function(e){
	if(gameMode == "play"){
	    // Switch tabs
	    $("#play_mode").hide();$("a#toggle_play").closest("li").removeClass("uk-active");
	    $("#draw_mode").show();$("a#toggle_draw").closest("li").addClass("uk-active")
	}
    });
    $("a#toggle_play").on('click', function(e){
	if(gameMode == "play"){
	    // Switch tabs
	    $("#draw_mode").hide();$("a#toggle_draw").closest("li").removeClass("uk-active");
	    $("#play_mode").css({"display":"flex"});$("a#toggle_play").closest("li").addClass("uk-active")
	}
	else{
	    // Request server to start game
	    console.log("Asking server to start game...");
	    packet = {
		"type": "startPlayMode",
		"player": username
	    }
	    ws.send(JSON.stringify(packet));
	    setTimeout(function(e){
		if(gameMode == "play"){
		    // Switch tabs
		    console.log("Switching tabs");
		    $("#draw_mode").hide();$("a#toggle_draw").closest("li").removeClass("uk-active");
		    $("#play_mode").css({"display":"flex"});$("a#toggle_play").closest("li").addClass("uk-active")
		}
	    }, 500);
	}
    });

    $("#submitCard").on('click', function(e){
	submitCard();
	clearCard();
    });
    $("#newCard").on('click', function(e) {
	clearCard();
    });

    $("#giphySearch").keyup(function(e){
	if(e.keyCode == "13"){
	    giphySearch();
	}
    });

    $("#giphySearchButton").click(function(e){
	    giphySearch();
    });
    
    
    $("#imageInsta").click(function(e){
	notice("TODO: Add insta feature");
    });
    $("#imageUpload").click(function(e){
	notice("TODO: Add upload feature");
    });
    $("#imageDraw").click(function(e){
	notice("TODO: Add draw feature");
    });
    
    range(22).forEach(function(e){
	var profURL = "/img/profiles/"+e+".jpg";
	$("#profile-options").append(
	    "<a href='javascript:chooseProfile("
	        + '"'
	        + profURL
	        + '"'
	        +");'><img class='search-result' src='"+profURL+"'/></a>"	    
	);
    });
    $('#imageModalContent').on('keyup keypress', function(e) {
	var keyCode = e.keyCode || e.which;
	if (keyCode === 13) {
	    e.preventDefault();
	    return false;
	}
    });
    $("#manualProfile").on('keyup', function(e){
	if(e.keyCode == 13){
	    const url = $(this).val();

	    $("#manual-img").attr("src", url).show();
	    $("#manual-img-href").attr('href',
				       "javascript:chooseProfile("
				       + '"'
				       + url
				       + '"'
				       +");"
				      );
	}
	else{
	    $("#manual-img").attr("src", "").hide();
	    
	}
    });

});
