"use strict";
this.name = "hoopy_blackjack";
this.author = "spara";
this.copyright = "2014 spara";
this.license = "CC BY-NC-SA 4.0";

//add interface
this.startUpComplete = this.shipExitedWitchspace = function () {
	var casinos = system.shipsWithRole("casinoship");
	if (casinos.length > 0) {
		for (var i = 0; i < casinos.length; i++) {
			casinos[i].setInterface("hoopy-blackjack", {
				title: expandMissionText("hoopy-blackjack-title"),
				category: expandMissionText("hoopy-gambling-category"),
				summary: expandMissionText("hoopy-blackjack-summary"),
				callback: this.$intro.bind(this)
			});
		}
	}
}

//init a new deck
this.$virginDeck = function () {
	var deck = new Array();
	var suits = ["triangle", "crescent", "square", "star"];
	for (var i = 0; i < 4; i++) {
		for (var j = 1; j < 14; j++) {
			var card = new Object();
			card.suit = suits[i];
			card.rank = j;
			card.double = 0;
			card.hide = 0;
			if (j > 10) card.value = 10;
			else if (j === 1) card.value = 11;
			else card.value = card.rank;
			deck.push(card);
		}
	}
	return deck;
}

//calculate the value of a hand
this.$calculateHandValue = function (cards) {
	var finished = false;
	while (!finished) {
		var sum = 0;
		for (var i = 0; i < cards.length; i++) {
			sum += cards[i].value;
		}
		if (sum > 21) {
			//change aces' value from 11 to 1
			for (var i = 0; i < cards.length; i++) {
				if (cards[i].value === 11) {
					cards[i].value = 1;
					break;
				}
			}
			//all aces have been changed, sum stands.
			if (i === cards.length)
				finished = true;
		}
		else finished = true;
	}
	return sum;
}

//intro screen
this.$intro = function () {

	var credits = "\n" + expandMissionText("hoopy-credits", { amount: formatCredits(player.credits, true, true) });

	//gambling choices
	var options = {
		"1_EXIT": expandMissionText("hoopy-exit")
	};
	if (player.credits >= 10)
		options["2_10"] = expandMissionText("hoopy-casino-bet", { amount: formatCredits(10, true, true) });
	else credits += expandMissionText("hoopy-no-credit");
	if (player.credits >= 100)
		options["3_50"] = expandMissionText("hoopy-casino-bet", { amount: formatCredits(50, true, true) });
	if (player.credits >= 500)
		options["4_100"] = expandMissionText("hoopy-casino-bet", { amount: formatCredits(100, true, true) });

	mission.runScreen({
		screenID: "hoopy_casino",
		titleKey: "hoopy-blackjack-title",
		message: expandMissionText("hoopy-blackjack-intro-story") + credits,
		model: "hoopy_casino_blackjack_card_intro",
		background: { name: "hoopy_table_bg2.png", height: 546 },
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
		function (choice) {
			if (choice === "2_10") this.$playGame(10);
			else if (choice === "3_50") this.$playGame(50);
			else if (choice === "4_100") this.$playGame(100);
		});
}

//first pay, then deal
this.$playGame = function (bet) {

	//pay up first
	player.credits -= bet;
	this.$bet = bet;//initial bet
	this.$totalBet = bet;//sum of all bets in round

	//init a new deck
	this.$playDeck = this.$virginDeck();

	//dealer initial hand
	var dealerHand = new Object();
	dealerHand.cards = [this.$drawCard(), this.$drawCard()];
	dealerHand.cards[1].hide = 1;
	this.$dealerHands = [dealerHand];

	//player initial hand
	var playerHand = new Object();
	playerHand.cards = [this.$drawCard(), this.$drawCard()];
	playerHand.bet = bet;
	this.$playerHands = [playerHand];

	//lets play some blackjack
	this.$deal(0);
}

this.$updateHandProps = function (hand, hands) {
	hand.value = this.$calculateHandValue(hand.cards);
	if (hand.value === 21) {
		if (hands.length === 1 && hand.cards.length === 2) {
			hand.status = "blackjack";
		}
		else hand.status = "21";
	}
	else if (hand.value > 21) hand.status = "busted";
	else if (hand.status !== "stand") hand.status = "hit";
}

//Deal
this.$deal = function () {

	//rotate till playable hand
	for (var hand = 0; hand < this.$playerHands.length; hand++) {
		var playerHand = this.$playerHands[hand];
		this.$updateHandProps(playerHand, this.$playerHands);
		if (playerHand.value < 21 && playerHand.status !== "stand")
			break;
	}

	//dealer's turn?
	if (hand === this.$playerHands.length) {
		this.$resolve();
		return;
	}

	//choices
	var options = {};
	if (playerHand.status === "hit") {
		options["1_HIT"] = expandMissionText("hoopy-blackjack-hit");
		options["2_STAND"] = expandMissionText("hoopy-blackjack-stand");
	}
	if (playerHand.cards.length === 2 && playerHand.status === "hit" && player.credits >= this.$bet) {
		options["3_DOUBLE"] = expandMissionText("hoopy-blackjack-double", { bet: formatCredits(this.$bet, true, true) });
	}
	if (playerHand.cards.length === 2 && (playerHand.cards[0].value === playerHand.cards[1].value || playerHand.cards[0].rank === playerHand.cards[1].rank) && this.$playerHands.length < 4) {
		options["4_SPLIT"] = expandMissionText("hoopy-blackjack-split", { bet: formatCredits(this.$bet, true, true) });
	}
	if (playerHand.cards.length === 2 && this.$playerHands.length === 1) {
		options["5_SURRENDER"] = expandMissionText("hoopy-blackjack-surrender");
	}

	//status message
	var message = expandMissionText("hoopy-blackjack-status", { player_hand: playerHand.value, bet: formatCredits(this.$totalBet, true, true), credits: formatCredits(player.credits, true, true) });

	mission.runScreen({
		screenID: "hoopy_casino",
		titleKey: "hoopy-blackjack-title",
		model: "hoopy_casino_blackjack_card_base",
		background: { name: "hoopy_table_bg2.png", height: 546 },
		message: message,
		spinModel: false,
		choices: options,
	},
		function (choice) {
			if (choice === "1_HIT") {
				playerHand.cards.push(this.$drawCard());
				this.$deal();
				return;
			}
			else if (choice === "2_STAND") {
				playerHand.status = "stand";
				this.$deal();
				return;
			}
			else if (choice === "3_DOUBLE") {
				playerHand.cards.push(this.$drawCard());
				this.$updateHandProps(playerHand, this.$playerHands);
				if (playerHand.value < 21) playerHand.status = "stand";
				player.credits -= this.$bet;
				this.$totalBet += this.$bet;
				playerHand.bet = 2 * playerHand.bet;
				this.$deal();
				return;
			}
			else if (choice === "4_SPLIT") {

				//limit to one card after splitting aces!!!!!!!
				if (playerHand.cards[0].rank === 1) {
					playerHand.cards[0].value = 11;
					playerHand.cards[1].value = 11;
				}
				player.credits -= this.$bet;
				this.$totalBet += this.$bet;
				var newHand = new Object();
				newHand.cards = [playerHand.cards.pop(), this.$drawCard()];
				newHand.bet = this.$bet;
				this.$playerHands.push(newHand);
				playerHand.cards.push(this.$drawCard());
				this.$deal();
				return;
			}
			else if (choice === "5_SURRENDER") {
				playerHand.status = "surrender";
				this.$resolve();
				return;
			}
			else {
				this.$intro();
				return;
			}
		}
	);

	this.$updateScreen();

	//update flasher markers
	//while playing: yellow - current hand, red - busted hand
	for (var i = 0; i < this.$playerHands.length; i++) {
		var status = this.$playerHands[i].status;
		if (i === hand)
			mission.displayModel.flashers[i].color = "yellowColor";
		else if (status === "busted")
			mission.displayModel.flashers[i].color = "redColor";
		else {
			mission.displayModel.flashers[i].position = [0, 0, 50];
		}
	}
	for (var j = i; j < 4; j++)
		mission.displayModel.flashers[j].position = [0, 0, 50];
}

this.$resolve = function () {

	var dealerHand = this.$dealerHands[0];
	this.$updateHandProps(dealerHand, this.$dealerHands);
	dealerHand.cards[1].hide = false;

	//check player for non-busted hands
	var busted = true;
	for (var i = 0; i < this.$playerHands.length; i++) {
		if (this.$playerHands[i].status !== "busted") {
			busted = false;
			break;
		}
	}

	//if all player cards are busted, dealer automatically wins
	if (busted || this.$playerHands[i].status === "surrender") {
		for (var i = 0; i < this.$playerHands.length; i++) {
			this.$playerHands[i].result = "loss";
		}
	}
	else {
		//start drawing cards until we go over 16.
		while (dealerHand.value < 17) {
			dealerHand.cards.push(this.$drawCard());
			this.$updateHandProps(dealerHand, this.$dealerHands);
		}
		//compare player hands to the dealer hand
		for (var i = 0; i < this.$playerHands.length; i++) {
			var playerHand = this.$playerHands[i];
			//if the player has not busted, we'll compare
			if (playerHand.status !== "busted") {
				//blackjack
				if (playerHand.status === "blackjack") {
					if (dealerHand.status === "blackjack")
						playerHand.result = "push";
					else playerHand.result = "win";
				}
				//push
				else if (dealerHand.value === playerHand.value)
					playerHand.result = "push";
				//win
				else if (dealerHand.value > 21 || (21 - playerHand.value < 21 - dealerHand.value))
					playerHand.result = "win";
				//loss
				else playerHand.result = "loss";
			}
			//if the player has busted, it's a loss
			else playerHand.result = "loss";
		}
	}

	//calculate the winnings
	var win = 0;
	for (var i = 0; i < this.$playerHands.length; i++) {
		var playerHand = this.$playerHands[i];
		if (playerHand.result === "win") {
			if (playerHand.status === "blackjack")
				win += 2.5 * playerHand.bet;
			else win += 2 * playerHand.bet;
		}
		else if (playerHand.result === "push")
			win += playerHand.bet;
		else if (playerHand.status === "surrender" && dealerHand.status !== "blackjack")
			win += playerHand.bet / 2;
	}
	player.credits += win;

	//status message
	var resultMessage = "";

	//player
	for (var i = 0; i < this.$playerHands.length; i++) {
		var playerHand = this.$playerHands[i]
		resultMessage += expandMissionText("hoopy-blackjack-playerhand");
		if (playerHand.status === "blackjack")
			resultMessage += expandMissionText("hoopy-blackjack-result-bj") + "\n";
		else if (playerHand.status === "busted")
			resultMessage += expandMissionText("hoopy-blackjack-result-bust") + "\n";
		else if (playerHand.result === "push")
			resultMessage += expandMissionText("hoopy-blackjack-result-push") + "\n";
		else if (playerHand.status === "surrender")
			resultMessage += expandMissionText("hoopy-blackjack-result-surrender") + "\n";
		else resultMessage += playerHand.value + "\n";
	}

	//dealer
	if (dealerHand.status === "blackjack")
		resultMessage += expandMissionText("hoopy-blackjack-dealer-status", { result: expandMissionText("hoopy-blackjack-result-bj") }) + "\n\n"
	else if (dealerHand.status === "busted")
		resultMessage += expandMissionText("hoopy-blackjack-dealer-status", { result: expandMissionText("hoopy-blackjack-result-bust") }) + "\n\n";
	else resultMessage += expandMissionText("hoopy-blackjack-dealer-status", { result: dealerHand.value }) + "\n\n";

	//winnings
	if (win - this.$totalBet > 0)
		resultMessage += expandMissionText("hoopy-blackjack-win", { amount: formatCredits(win - this.$totalBet, true, true) }) + "\n";
	else if (win - this.$totalBet < 0)
		resultMessage += expandMissionText("hoopy-blackjack-lose", { amount: formatCredits(this.$totalBet - win, true, true) }) + "\n";
	else resultMessage += expandMissionText("hoopy-blackjack-even") + "\n"

	resultMessage += expandMissionText("hoopy-credits", { amount: formatCredits(player.credits, true, true) });

	var options = {
		"2_REBET": expandMissionText("hoopy-casino-change-bet"),
		"3_EXIT": expandMissionText("hoopy-exit")
	};
	if (player.credits >= this.$bet)
		options["1_AGAIN"] = expandMissionText("hoopy-dealagain", { amount: formatCredits(this.$bet, true, true) });

	mission.runScreen({
		screenID: "hoopy_casino",
		titleKey: "hoopy-blackjack-title",
		model: "hoopy_casino_blackjack_card_base",
		message: resultMessage,
		spinModel: false,
		background: { name: "hoopy_table_bg2.png", height: 546 },
		choices: options,
		allowInterrupt: true,
		exitScreen: "GUI_SCREEN_INTERFACES"
	},
		function (choice) {
			if (choice === "1_AGAIN") {
				this.$playGame(this.$bet);
				return;
			}
			else if (choice === "2_REBET") {
				this.$intro();
				return;
			}
		});

	this.$updateScreen(-1);

	//red: lose
	//green: win
	//yellow: push
	for (var i = 0; i < this.$playerHands.length; i++) {
		var result = this.$playerHands[i].result;
		if (result === "win")
			mission.displayModel.flashers[i].color = "greenColor";
		else if (result === "loss")
			mission.displayModel.flashers[i].color = "redColor";
		else mission.displayModel.flashers[i].color = "yellowColor";
	}
	for (var j = i; j < 4; j++)
		mission.displayModel.flashers[j].position = [0, 0, 50];
}

//draws a card from the current deck in play
this.$drawCard = function () {
	return this.$playDeck.splice(Math.floor(this.$playDeck.length * Math.random()), 1)[0];
}

//update textures and positions for cards
this.$updateScreen = function () {
	//player cards subents 0-10, 11-21, 22 -32, 33-43
	//dealer cards subents 44-54

	//player cards
	for (var i = 0; i < this.$playerHands.length; i++) {
		//show player hand
		var playerHand = this.$playerHands[i];
		for (var j = 0; j < playerHand.cards.length; j++) {
			var card = playerHand.cards[j];
			var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
			var place = i * 11 + j;
			mission.displayModel.subEntities[place].setMaterials({ "casino_poker_card_diffuse.png": { diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor" } });
		}
		//double down
		if (playerHand.bet === 2 * this.$bet) {
			mission.displayModel.subEntities[place].orientation = [0.5, 0.5, 0.5, 0.5];
		}
		//hide non used player subents from view
		for (var k = j; k < 11; k++) this.$hideCard(i * 11 + k);
	}
	//hide non used player subents from view
	for (var k = i * 11; k < 44; k++) this.$hideCard(k);

	//dealer cards
	var dealerHand = this.$dealerHands[0];
	for (var j = 0; j < dealerHand.cards.length; j++) {
		var card = dealerHand.cards[j];
		if (card.hide)
			var fileName = "casino_blackjack_card_diffuse.png";
		else
			var fileName = "hoopy_card_" + card.suit + "_" + card.rank + ".png";
		mission.displayModel.subEntities[4 * 11 + j].setMaterials({ "casino_poker_card_diffuse.png": { diffuse_map: fileName, emission_map: fileName, emission_modulate_color: "darkGrayColor" } });
	}
	//hide non used dealer subents from view
	for (var k = 4 * 11 + j; k < 54; k++) this.$hideCard(k);
}

//moves the cards to the centerline and turns them out of view
this.$hideCard = function (place) {
	var position = mission.displayModel.subEntities[place].position;
	position[2] = 0;
	mission.displayModel.subEntities[place].position = position;
	var orientation = [0, 0, 0, 1];
	mission.displayModel.subEntities[place].orientation = orientation;
}
