//This is the primary javascript file for Card Conjurer, a program by Kyle Burton that draws custom Magic: The Gathering cards!


//============================================//
//              Initialization                //
//============================================//
//The following bits of code are run immediatly to initialize the program while allowing the variables to remain global.
//Define initial variables
var borderPath
var secondColor
var thirdColor
var titleRightShift = 0
var typeRightShift = 0
var textBaselineShift = 0
var imagesToLoad

//Determine browser
var isChrome = navigator.userAgent.indexOf('Chrome') > -1
var isExplorer = navigator.userAgent.indexOf('MSIE') > -1
var isFirefox = navigator.userAgent.indexOf('Firefox') > -1
var isSafari = navigator.userAgent.indexOf("Safari") > -1
if (isChrome == true && isSafari == true) {
	isSafari = false
}
if (isSafari == true) {
    textBaselineShift = -0.17
}

//Set up canvas
var canvas = document.getElementById("canvas")
var card = canvas.getContext("2d")

//Create the canvas for creating the border image
var borderCanvas = document.createElement("canvas")
var border = borderCanvas.getContext("2d")
document.body.appendChild(borderCanvas)

//load template images (images that may change based off of the selected template)
var imgListTemplate = ["multiMask", "rareStampMask", "frameMask", "legendFrameMask", "borderMask", "artMask", "abilityLineOdd", "abilityLineEven", "rulesMask", "typeMask", "titleMask"]
for (var i = 0; i < imgListTemplate.length; i ++) {
	var imgName = "img" + imgListTemplate[i].charAt(0).toUpperCase() + imgListTemplate[i].slice(1)
	window[imgName] = new Image()
	window[imgName].crossOrigin = "anonymous"
}

//Load border images (images that are determined by border settings)
var imgListBorder = ["borderColor", "secondBorderColor", "thirdBorderColor", "artifactBorderColor", "borderCreature", "borderLegendary", "secondBorderLegendary", "borderRareStamp", "secondBorderRareStamp", "borderNyx", "secondBorderNyx", "borderMiracle", "secondBorderMiracle", "borderFlipIcon", "borderFlipCircle", "borderFlipTip", "borderFlippedDark", "secondBorderFlippedDark"]
for (var i = 0; i < imgListBorder.length; i ++) {
	var imgName = "img" + imgListBorder[i].charAt(0).toUpperCase() + imgListBorder[i].slice(1)
	window[imgName] = new Image()
	window[imgName].crossOrigin = "anonymous"
	imgListBorder[i] = window[imgName]
	imgListBorder[i].onload = function() {
		if (this.hasToLoad == true) {
			this.hasToLoad = false
			imagesToLoad --
			if (imagesToLoad == 0) {
				createBorder()
			}
		}
	}
}

//Load dynamic images (images that are input by the user)
var imgListUser = ["art", "setSymbol", "watermark", "border"]
for (var i = 0; i < imgListUser.length; i ++) {
	var imgName = "img" + imgListUser[i].charAt(0).toUpperCase() + imgListUser[i].slice(1)
	window[imgName] = new Image()
	window[imgName].crossOrigin = "anonymous"
	window[imgName].onload = function() {
		//If both tasks are required, it will make white pixels transparent first. That way they also get cropped out.
		if (this.whiteToTransparent == false) {
			this.whiteToTransparent = true
			whiteToTransparent(imgWatermark)
		} else if (this.cropped == false) {
			this.cropped = true
			autocrop(this.src, this)
		}
	}
}

//Load static images
var imgListStatic = ["artistBrush", "foil", "multiGradient", "rareStamp", "cardMask", "bar", "identity"]
for (var i = 0; i < imgListStatic.length; i ++) {
	var imgName = "img" + imgListStatic[i].charAt(0).toUpperCase() + imgListStatic[i].slice(1)
	window[imgName] = new Image()
	window[imgName].src = "data/borders/" + imgListStatic[i] + ".png"
}

//Mana symbol Array setup
var manaSymbolCode = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "w", "u", "b", "r", "g", "2w", "2u", "2b", "2r", "2g", "pw", "pu", "pb", "pr", "pg", "wu", "wb", "ub", "ur", "br", "bg", "rg", "rw", "gw", "gu", "x", "s", "c", "t","untap", "e", "y", "z", "1/2", "inf", "chaos", "plane", "l+", "l-", "l0"]
var manaSymbolImages = new Array()
for (var i = 0; i < manaSymbolCode.length; i++) {
	manaSymbolImages[i] = new Image()
	manaSymbolImages[i].src = "data/manaSymbols/" + i + ".png"
	manaSymbolImages[i].name = i
	manaSymbolImages[i].onload = function() {
		document.getElementById(this.name).src = this.src
	}
}

//Go ahead and load the first border
loadScript("data/borders/defaultBorder.js")

//load first set symbol
loadSetSymbol()

//Randomize the sample cards at the bottom
randomizeSampleCards(12)

//Set up the initial clock!
var cardClockInterval
setTimeout(function() {
    cardClockInterval = setInterval(cardClock, 1000 / document.getElementById("inputFPS").value)
}, 200)

//It's easier to generate the mana symbol list via js, so do it here
var symbolList = ""
	for (var i = 0; i < manaSymbolCode.length; i++) {
		symbolList += "<div class='manaSymbol' alt='...'>" + manaSymbolCode[i] + "<br/>" + "<img id='" + i + "'></img></div>"
	}
document.getElementById("symbolList").innerHTML += symbolList


//============================================//
//       Card clock and changing frames!      //
//============================================//
//Runs ten times every second (main loop)
function cardClock() {
	//fixes the global alpha just incase...
	//Insures that the corners of the final image are transparent
	card.globalCompositeOperation = "source-over"
	card.mask("imgCardMask,source-over", "none",document.getElementById("inputColor").value)
	card.globalCompositeOperation = "source-atop"
	//Draws the card image, then...
	drawPicture()
	//draws the card frame on top
    card.drawImage(imgBorder, 0, 0, cardWidth, cardHeight)
	//draws the set symbol, mana cost, and watermark
	drawSetSymbol()
	drawManaCost()
	drawWatermark()
	//writes all the text: name, type, rules...
	writeText()
	//Runs any special function that a card may have, including bottom information.
	window[uniqueFunctionName]()
	//A shiny foil overlay!
	if(document.getElementById("checkboxFoil").checked == true) {
		card.drawImage(imgFoil, 0, 0, cardWidth, cardHeight)
	}
	//These are for pinpointing coordinates while adjusting values for new border types
	if (document.getElementById("checkboxDebuggerLine").checked == true) {
		card.strokeStyle = "#ff0000"
		//Vertical Line
		card.beginPath()
		card.moveTo(titleY, 0)
		card.lineTo(titleY, cardHeight)
		card.stroke()
		//Horizontal Line
		card.beginPath()
		card.moveTo(0, titleX)
		card.lineTo(cardWidth, titleX)
		card.stroke()
		console.log("debugging")
	}
}

//The two following functions load border images
function changeTemplate() {
	//the loadScript function is located in data/scripts/loadScript.js. It sets values to variables such as set symbol coordinates or title font
	borderPath = "data/borders/" + document.getElementById("borderSelection").value
	loadScript("data/borders/defaultBorder.js")
}
function finishTemplate() {
	//This is a seperate function to insure that the border.js file finishes running before running a few last commands
	canvas.width = cardWidth
	canvas.height = cardHeight
	borderCanvas.width = cardWidth
	borderCanvas.height = cardHeight
	maskCanvas.width = cardWidth
	maskCanvas.height = cardHeight
	imgArtMask.src = borderPath + "artMask.png"
	document.getElementById("colorSelection").value = "white"
	updateBorder()
}
//Loads the images for the card frame, power toughness box, and rare stamp
function updateBorder() {
	secondColor = document.getElementById("checkboxSecondColor").checked
	thirdColor = document.getElementById("checkboxThirdColor").checked
	var firstColorPath = borderPath + document.getElementById("colorSelection").value
	var secondColorPath = borderPath + document.getElementById("secondColorSelection").value
	var thirdColorPath = borderPath + document.getElementById("thirdColorSelection").value
	var altframe = ""
	imgBorderColor.src = firstColorPath + "/frame.png"
	imgSecondBorderColor.src = secondColorPath + "/frame.png"
	imgThirdBorderColor.src = thirdColorPath + "/frame.png"
	if (artifactBorder == true) {
		imgArtifactBorderColor.src = borderPath + "artifact/frame.png"
	}
	if (document.getElementById("checkboxFlippedDark").checked == true && flipBorder == true) {
		altframe = "dark"
	} else {
		altframe = ""
	}
	if (creatureBorder == true) {
		if (thirdColor == true) {
			imgBorderCreature.src = thirdColorPath + "/" +  altframe + "pt.png"
		} else if (secondColor == true) {
			imgBorderCreature.src = secondColorPath + "/" +  altframe + "pt.png"
		} else {
			imgBorderCreature.src = firstColorPath + "/" +  altframe + "pt.png"
		}
	}
	if (legendaryBorder == true) {
		imgBorderLegendary.src = firstColorPath + "/legendary.png"
		imgSecondBorderLegendary.src = secondColorPath + "/legendary.png"
	}
	if (stampBorder == true) {
		imgBorderRareStamp.src = firstColorPath + "/stamp.png"
		imgSecondBorderRareStamp.src = secondColorPath + "/stamp.png"
	}
	if (nyxBorder == true) {
		if (artifactBorder == true && document.getElementById("checkboxArtifact").checked == true) {
			imgBorderNyx.src = borderPath + "artifact/nyx.png"
		} else if (thirdColor == true) {
			imgBorderNyx.src = thirdColorPath + "/nyx.png"
		} else {
			imgBorderNyx.src = firstColorPath + "/nyx.png"
			imgSecondBorderNyx.src = secondColorPath + "/nyx.png"
		}
	}
	if (miracleBorder == true) {
		if (thirdColor == true) {
			imgBorderMiracle.src = thirdColorPath + "/" +  altframe + "miracle.png"
		} else {
			imgBorderMiracle.src = firstColorPath + "/" +  altframe + "miracle.png"
			imgSecondBorderMiracle.src = secondColorPath + "/" +  altframe + "miracle.png"
		}
	}
	if (flipBorder == true) {
		if (thirdColor == true) {
			imgBorderFlippedDark.src = thirdColorPath + "/flippedDark.png"
		} else {
			imgBorderFlippedDark.src = firstColorPath + "/flippedDark.png"
			imgSecondBorderFlippedDark.src = secondColorPath + "/flippedDark.png"
		}
		if (secondColor == true) {
			imgBorderFlipTip.src = secondColorPath + "/flipTip.png"
		} else {
			imgBorderFlipTip.src = firstColorPath + "/flipTip.png"
		}
		imgBorderFlipCircle.src = firstColorPath + "/flipCircle.png"
		imgBorderFlipIcon.src = "data/borders/icons/" + document.getElementById("inputFlipIcon").value
	}
	//This allows all the images to be loaded
	imagesToLoad = 0
	//Makes a count of all images that are loading, also tags them
	for (var i = 0; i < imgListBorder.length; i++) {
		if (imgListBorder[i].complete == false) {
			imagesToLoad ++
			imgListBorder[i].hasToLoad = true
		}
	}
	//If no images needed to be loaded, runs the createBorder function anyways
	if (imagesToLoad == 0) {
		createBorder()
	}
}
//Once the border images have finished loading, they are all drawn into a temporary canvas then saved to a single image
function createBorder() {
	//These if else statements check to see whether or not to draw different parts of the card, like the legendary border or rare stamp, and draws them in the appropriate order so that when multiple border colors are used the gradients overlap correctly
	//BACKGROUND COLOR
	border.clearRect(0, 0, cardWidth, cardHeight)
	if (document.getElementById("colorSelection").value.includes("clear") == true) {
		border.mask("imgArtMask,source-over;imgFrameMask,destination-out", "none", document.getElementById("inputColor").value)
	} else if (document.getElementById("checkboxBorderless").checked == false) {
		border.mask("imgArtMask,source-over", "none", document.getElementById("inputColor").value)
	}
	//Draws the silver border usually on un-cards
	if (document.getElementById("checkboxSilverBorder").checked == true) {
		border.mask("imgBorderMask,source-over", "none", "#a3aeb7")
	}
	//MAIN CARD FRAME
	border.mask("imgFrameMask,source-over", imgBorderColor)
	if (secondColor == true && secondBorder == true) {
		border.mask("imgMultiGradient,source-over;imgFrameMask,source-in", imgSecondBorderColor)
	}
	if (thirdColor == true && thirdBorder == true) {
		border.mask("imgMultiMask,source-over;imgFrameMask,source-in", imgThirdBorderColor)
	}
	if (artifactBorder == true && document.getElementById("checkboxArtifact").checked == true) {
		border.mask("imgMultiMask,source-over;imgFrameMask,source-in;imgTitleMask,destination-out;imgTypeMask,destination-out", imgArtifactBorderColor)
	}
	//NYX
	if (document.getElementById("checkboxNyx").checked == true && nyxBorder == true) {
		if (thirdColor == true || (document.getElementById("checkboxArtifact").checked == true && artifactBorder == true)) {
			border.mask("imgMultiMask,source-over;imgFrameMask,source-in", imgBorderNyx)
		} else {
			border.mask("imgFrameMask,source-over", imgBorderNyx)
			if (secondColor == true) {
				border.mask("imgMultiGradient,source-over;imgFrameMask,source-in", imgSecondBorderNyx)
			}
		}	
	}
	//MIRACLE
	if (document.getElementById("checkboxMiracle").checked == true && miracleBorder == true && (document.getElementById("checkboxFlippedDark").checked == false || flipBorder == false)) {
		if (thirdColor == true) {
			border.mask("imgFrameMask,source-over", imgBorderMiracle)
		} else {
			border.mask("imgFrameMask,source-over", imgBorderMiracle)
			if (secondColor == true) {
				border.mask("imgMultiGradient,source-over;imgFrameMask,source-in", imgSecondBorderMiracle)
			}
		}
	}
	//LEGENDARY
	if (document.getElementById("checkboxLegendary").checked == true && legendaryBorder == true) {
		border.mask("imgLegendFrameMask,source-over", imgBorderLegendary)
		if (secondColor == true) {
			border.mask("imgMultiGradient,source-over;imgLegendFrameMask,source-in", imgSecondBorderLegendary)
		}
		//redraws the custom-color border to match the legendary frame
		if (document.getElementById("checkboxBorderless").checked != true) {
			border.mask("imgLegendFrameMask,source-over;imgBorderMask,source-out", "none", document.getElementById("inputColor").value)
		}
		//redraws the silver border usually on un-cards to match the legendary frame
		if (document.getElementById("checkboxSilverBorder").checked == true) {
			border.mask("imgLegendFrameMask,source-over;imgBorderMask,source-out", "none", "#a3aeb7")
		}
	}
	//FLIP CARDS
	if (flipBorder == true) {
		if (document.getElementById("checkboxFlippedDark").checked == true && flipBorder == true) {
			if (thirdColor == true) {
				border.mask("imgFrameMask,source-over", imgBorderFlippedDark)
			} else {
				border.mask("imgFrameMask,source-over", imgBorderFlippedDark)
				if (secondColor == true) {
					border.mask("imgMultiGradient,source-over", imgSecondBorderFlippedDark)
				}
			}
		}
		//redraws the miracle border if required to match with the newer darker overlay
		if (document.getElementById("checkboxMiracle").checked == true && miracleBorder == true && (document.getElementById("checkboxLegendary").checked == false || legendaryBorder == false)) {
			if (thirdColor == true) {
				border.mask("imgFrameMask,source-over", imgBorderMiracle)
			} else {
				border.mask("imgFrameMask,source-over", imgBorderMiracle)
				if (secondColor == true) {
					border.mask("imgMultiGradient,source-over;imgFrameMask,source-in", imgSecondBorderMiracle)
				}
			}
		}
		if (document.getElementById("checkboxFlipIcon").checked == true || document.getElementById("checkboxFlippedDark").checked == true) {
			border.drawImage(imgBorderFlipCircle, imgBorderFlipCircle.imgX, imgBorderFlipCircle.imgY, imgBorderFlipCircle.imgW, imgBorderFlipCircle.imgH)
			border.drawImage(imgBorderFlipIcon, 39, 51, 60, 60)
		}
		if (document.getElementById("checkboxFlipTip").checked == true) {
			border.drawImage(imgBorderFlipTip, imgBorderFlipTip.imgX, imgBorderFlipTip.imgY, imgBorderFlipTip.imgW, imgBorderFlipTip.imgH)
		}
		if (document.getElementById("checkboxFlipIcon").checked == true || document.getElementById("checkboxFlippedDark").checked == true) {
			titleRightShift = 50
		} else {
			titleRightShift = 0
		}
	}
	//CLEAR ANYTHING UNWANTED
	border.globalCompositeOperation = "destination-out"
	if (document.getElementById("checkboxRulesVisibility").checked == false && imgRulesMask.width > 0) {
		border.drawImage(imgRulesMask, 0, 0, cardWidth, cardHeight)
	}
	if (document.getElementById("checkboxTypeVisibility").checked == false && imgTypeMask.width > 0) {
		border.drawImage(imgTypeMask, 0, 0, cardWidth, cardHeight)
	}
	if (document.getElementById("checkboxTitleVisibility").checked == false && imgTitleMask.width > 0) {
		border.drawImage(imgTitleMask, 0, 0, cardWidth, cardHeight)
	}
	// if (document.getElementById("checkboxLegendary").checked == true && legendaryBorder == true && document.getElementById("checkboxBorderless").checked == true && document.getElementById("checkboxSilverBorder").checked == false) {
	// 	border.drawImage(imgBorderMask, 0, 0, cardWidth, cardHeight)
	// }
	border.globalCompositeOperation = "source-over"
	//COLOR IDENTITY
	if (document.getElementById("checkboxIdentity").checked == true) {
		var identityList = document.getElementById("inputIdentity").value.toLowerCase().split(" ")
		var angleSize = Math.PI * 2 / identityList.length
		var identityRadius = 14
		var identityX = typeX + 8
		var identityY = typeY + 15
		switch (identityList.length) {
			case 1:
			var originAngle = 0
			break;
			case 2:
			var originAngle = 3 * Math.PI / 4
			break;
			case 3:
			var originAngle = 7 * Math.PI / 6
			break;
			case 4:
			var originAngle = 3 * Math.PI / 2
			break;
			case 5:
			var originAngle = 13 * Math.PI / 10
			break;
			default:
			var originAngle = 0
		}
		for (var i = 0; i < identityList.length; i ++) {
			switch (identityList[i]) {
				case "w":
				border.fillStyle = "#f3f2ef"
				break;
				case "u":
				border.fillStyle = "#1d7097"
				break;
				case "b":
				border.fillStyle = "#31302e"
				break;
				case "r":
				border.fillStyle = "#bf544c"
				break;
				case "g":
				border.fillStyle = "#1c6449"
				break;
				case "m":
				border.fillStyle = "#e3d591"
				break;
				default:
				border.fillStyle = "#e0e0e0"
			}
			var startAngle = originAngle + i * angleSize
			border.beginPath()
			border.moveTo(identityX, identityY)
			border.arc(identityX, identityY, identityRadius, startAngle, startAngle + angleSize)
			border.lineTo(identityX, identityY)
			border.fill()
		}
		border.drawImage(imgIdentity, identityX - identityRadius, identityY - identityRadius, 2 * identityRadius, 2 * identityRadius)
		typeRightShift = 33
	} else {
		typeRightShift = 0
	}
	//RARE STAMP
	if (document.getElementById("checkboxRareStamp").checked == true && stampBorder == true) {
        imgBorderRareStamp.imgValues(329, rareStampY - 15, 90, 50, "imgSecondBorderRareStamp,imgRareStampMask")
		border.mask("imgCardMask,source-over", imgBorderRareStamp)
		if (document.getElementById("checkboxSecondColor").checked == true) {
			border.mask("imgMultiGradient,source-over", imgSecondBorderRareStamp)
		}
		if (document.getElementById("checkboxBorderless").checked != true) {
			//Draws over the rare stamp (part that's usually black) to match custom border color
	        border.mask("imgCardMask,source-over", imgRareStampMask, document.getElementById("inputColor").value)
	    }
		//This is when the holo stamp is drawn
		border.drawImage(imgRareStamp, 340, rareStampY, 70, 37)
	}
	imgBorder.src = borderCanvas.toDataURL()
}


//============================================//
//            Drawing on the card             //
//============================================//
//Draw card art
function drawPicture() {
	//scales the card art and draws it
	card.rotate(document.getElementById("imageRotation").value * Math.PI / 180);
	var imageScale = document.getElementById("imageSize").value * 0.01
	var imageLeftShift = parseInt(document.getElementById("imageLeft").value)
	var imageUpShift = parseInt(document.getElementById("imageUp").value)
	if (imgArt.width > 0) {
		card.drawImage(imgArt, artX - imageLeftShift, artY - imageUpShift, imgArt.width * imageScale, imgArt.height * imageScale)
	}
	card.rotate(document.getElementById("imageRotation").value * Math.PI / -180);
}

//Draw the set symbol
function drawSetSymbol() {
	//scales the set symbol so that it fits in the correct area and centers it
	if (imgSetSymbol.width > 0 && document.getElementById("checkboxSetSymbol").checked == true) {
		var height = setSymbolHeight
		var width = imgSetSymbol.width * (height / imgSetSymbol.height)
		if (width > setSymbolWidth) {
			width = setSymbolWidth
			height = imgSetSymbol.height * (width / imgSetSymbol.width)
		}
		height *= document.getElementById("setSymbolSize").value / 100
		width *= document.getElementById("setSymbolSize").value / 100
		var y = setSymbolY - height / 2
		var x = setSymbolRight - width / centerSetSymbol
		card.drawImage(imgSetSymbol, x, y, width, height)
	}
}

//Draw the watermark
function drawWatermark() {
	//The watermark is centered/scaled just like the set symbol
	if (imgWatermark.width > 0 && document.getElementById("checkboxWatermark").checked == true) {
		var height = watermarkHeight
		var width = imgWatermark.width * (height / imgWatermark.height)
		if (width > watermarkWidth) {
			width = watermarkWidth
			height = imgWatermark.height * (width / imgWatermark.width)
		}
		var x = cardWidth / 2 - width / 2
		var y = watermarkY - height / 2
        imgWatermark.imgValues(x, y, width, height)
		//globalAlpha insures that the watermark is drawn partially transparent. This value may not be perfect but the watermark colors are calibrated to it
		card.globalAlpha = document.getElementById("inputWatermarkOpacity").value
	    //if the following if statement is true, the watermark will be drawn in two halves of the chosen colors. Otherwise, a single watermark of the first chosen color is drawn.
	    if (document.getElementById("checkboxSecondWatermarkColor").checked == true) {
            card.mask("imgMultiGradient,source-over;imgCardMask,source-out", imgWatermark, document.getElementById("watermarkColorSelection").value)
	    	card.mask("imgMultiGradient,source-over", imgWatermark, document.getElementById("secondWatermarkColorSelection").value)
	    } else {
	    	card.mask("imgCardMask,source-over", imgWatermark, document.getElementById("watermarkColorSelection").value)
	    }
	}
	card.globalAlpha = 1
}

//Draw the mana cost
function drawManaCost() {
	//the symbols string splits the mana cost input into an array of strings which is then put into a for loop that draws the appropriate set symbol then adjusts the xShift so the set symbols are spaced properly
	card.fillStyle = "Black"
	var symbols = document.getElementById("inputCost").value.toLowerCase().split(" ")
	var xShift = 0
	for (var n = symbols.length; n > -1; n--) {
		if (manaSymbolCode.indexOf(symbols[n]) != -1) {
			card.beginPath()
			card.arc(manaCostX + xShift + manaCostRadius - 1, manaCostY + manaCostRadius + 3.5, manaCostRadius, 0, 6.29, false)
			card.fill()
			card.drawImage(manaSymbolImages[manaSymbolCode.indexOf(symbols[n])], manaCostX + xShift, manaCostY, manaCostRadius * 2, manaCostRadius * 2)
			xShift -= 39
		}
	}
}

//Write card text (title, type, pt, and rules)
function writeText() {
	//Draws the entered text onto the card, also draws the power/toughness box if necessary
	//All use these:
	card.textBaseline = "top"
	// if (flipBorder == true && document.getElementById("checkboxFlippedDark").checked == true) {
	// 	card.fillStyle = "White"//attention
	// } else {
	// 	card.fillStyle = "Black"
	// }
	//Title
	card.fillStyle = document.getElementById("inputTitleColor").value
	card.textAlign = titleAlign
	canvas.style.letterSpacing = titleFontSpacing
	card.font = titleFont	
	card.fillText(document.getElementById("inputName").value, titleX + titleRightShift, titleY + textBaselineShift * card.font.split("px")[0])
	//Type
	card.fillStyle = document.getElementById("inputTypeColor").value
	card.textAlign = typeAlign
	canvas.style.letterSpacing = typeFontSpacing
	card.font = typeFont
	card.fillText(document.getElementById("inputType").value, typeX + typeRightShift, typeY + textBaselineShift * card.font.split("px")[0])
	//Power/Toughness
	if (document.getElementById("checkboxCreature").checked == true && creatureBorder == true) {
		// if (imgBorderCreature.src.substr(imgBorderCreature.src.length - 14) == "vehicle/pt.png" || borderPath == "data/borders/planeswalker/") {
		// 	card.fillStyle = "White"//attention
		// }
		card.fillStyle = document.getElementById("inputCreatureColor").value
		card.textAlign = "center"
		card.drawImage(imgBorderCreature, imgBorderCreature.imgX, imgBorderCreature.imgY, imgBorderCreature.imgW, imgBorderCreature.imgH)
		canvas.style.letterSpacing = ptFontSpacing
		card.font = ptFont
		powerToughness = document.getElementById("inputPowerToughness").value
		card.fillText(powerToughness, ptTextX, ptTextY + textBaselineShift * card.font.split("px")[0])
	}
	card.textAlign = "left"
	// card.fillStyle = "Black"//attention
	//Rules Text
	card.fillStyle = document.getElementById("inputRulesColor").value
	canvas.style.letterSpacing = textFontSpacing + "px"
	card.font = document.getElementById("textSize").value + textFont
	var text = document.getElementById("inputText").value
	drawText(text, textX, textY)
	//Flip Tip?
	if (document.getElementById("checkboxFlipTip").checked == true && flipBorder == true) {
		card.textAlign = "right"
		card.fillStyle="#666"
		canvas.style.letterSpacing = "0px"
		card.font = "28px belerenb"
		card.fillText(document.getElementById("inputFlipTip").value, 688, 886 + textBaselineShift * card.font.split("px")[0])
		card.textAlign = "left"
	}
}

//Bottom info on M15 cards
function bottomInfoM15() {
	card.fillStyle = document.getElementById("inputInfoColor").value
	var shiftInfo = 446
	canvas.style.letterSpacing = "1.5px"
	card.font = "19px relaymedium"
	var bottomLine = document.getElementById("inputSet").value + " \u00b7 " + document.getElementById("inputLanguage").value
	card.fillText(bottomLine, 48, infoY + textBaselineShift * card.font.split("px")[0])
	var artistBrushShift = card.measureText(bottomLine).width + 58
    imgArtistBrush.imgValues(artistBrushShift, infoY + 2, 21, 13)
	card.mask("imgArtMask,source-over", imgArtistBrush, card.fillStyle)
	card.font = "18px relaymedium"
	canvas.style.letterSpacing = "2px"
	if (card.measureText(document.getElementById("inputNumber").value).width > artistBrushShift - 58) {
		artistBrushShift = card.measureText(document.getElementById("inputNumber").value).width + 58
	}
	card.fillText(document.getElementById("inputNumber").value, 49, infoY - 20 + textBaselineShift * card.font.split("px")[0])
	card.fillText(document.getElementById("inputRarity").value, artistBrushShift - 1, infoY - 20 + textBaselineShift * card.font.split("px")[0])
	if (446 < artistBrushShift  + card.measureText(document.getElementById("inputRarity").value).width && document.getElementById("checkboxCreature").checked == false) {
		shiftInfo = artistBrushShift  + card.measureText(document.getElementById("inputRarity").value).width + 5
	}
	canvas.style.letterSpacing = "-0.1px"
	card.font = "22px matrixbsc"
	card.fillText(document.getElementById("inputArtist").value, artistBrushShift + 21, infoY + textBaselineShift * card.font.split("px")[0])
	if (446 < artistBrushShift + 21 + card.measureText(document.getElementById("inputArtist").value).width && document.getElementById("checkboxCreature").checked == true) {
		shiftInfo = artistBrushShift + card.measureText(document.getElementById("inputArtist").value).width + 26
	}
	//This is where "CC —" is hardcoded. The only reason is to prevent users from easily typing in the trademark and copyright that's usually on real cards. It's also there so I can see if a card was created with my program, it makes me feel good :)
	if (document.getElementById("inputInfo").value != "") {
		canvas.style.letterSpacing = "0px"
		card.font = "17px mplantin"
		var bottomInfo = "CC \u2014 " + document.getElementById("inputInfo").value
		if (bottomInfo == "CC \u2014 secretcode") {
			var date = new Date()
			var year = date.getFullYear()
			bottomInfo = "\u2122 & \u00a9 " + year + " Wizards of the Coast"
		}
		if (document.getElementById("checkboxCreature").checked == true) {
			card.fillText(bottomInfo, shiftInfo, infoY + 1 + textBaselineShift * card.font.split("px")[0])
		} else {
			card.fillText(bottomInfo, shiftInfo, infoY - 17 + textBaselineShift * card.font.split("px")[0])
		}
	}
}


//============================================//
//         Text processor! (kind of)          //
//============================================//
//Write the rules and flavor text!
function drawText(text, xCoord, yCoord) {
	var x = xCoord
	var lineSpace = parseInt(document.getElementById("textShift").value, 10)
	var textSize = parseInt(document.getElementById("textSize").value, 10)
	var y = yCoord + parseInt(document.getElementById("textDown").value, 10)
	var textXShift = 0
	var words = (text).split(" ")
	var line = ""
	var tempTextWidth = textWidth
	for (var wordIndex = 0; wordIndex < words.length; wordIndex ++) {
		if (words[wordIndex].includes("<") == false || words[wordIndex].includes(">") == false) {
			//Just a regular old word
			testLine = line + words[wordIndex]
			var lineWidth = card.measureText(testLine).width
			if (lineWidth + textXShift + x > tempTextWidth && wordIndex > 0) {
				//Word is too big
				card.fillText(line, x + textXShift, y + textBaselineShift * card.font.split("px")[0])
				line = words[wordIndex] + " "
				y += textSize + 1
				textXShift = 0
			} else {
				//Word fits
				line = testLine + " "
			}
			if (wordIndex + 1 == words.length) {
				card.fillText(line, x + textXShift, y + textBaselineShift * card.font.split("px")[0])
			}
		} else {
			//Symbols and more!
			var splitWord = words[wordIndex].split("<")
			for (var splitIndex = 0; splitIndex < splitWord.length; splitIndex ++) {
				//Write what's there first!
				card.fillText(line, x + textXShift, y + textBaselineShift * card.font.split("px")[0])
				textXShift += card.measureText(line).width
				line = ""
				if (splitWord[splitIndex].includes(">")) {
					var plainWord = ""
					var megaSplit = splitWord[splitIndex].split(">")
					//series of if statements to determine an action based off of the given code
					if (megaSplit[0] == "i") {
						canvas.style.letterSpacing = textFontSpacing * 1/3 + "px"
						card.font = textSize * italicSize + textFont + "i"
					} else if (megaSplit[0] == "/i") {
						canvas.style.letterSpacing = textFontSpacing + "px"
						card.font = textSize + textFont
					} else if (megaSplit[0] == "center") {
						card.textAlign="center"
						x = cardWidth / 2
						tempTextWidth = textWidth * 1.5
					} else if (megaSplit[0] == "right") {
						card.textAlign="right"
						tempTextWidth = textWidth * 1.9
						x = cardWidth - xCoord
					} else if (megaSplit[0] == "left") {
						card.textAlign="left"
						tempTextWidth = textWidth
						x = xCoord
					} else if (megaSplit[0] == "line") {
						textXShift = 0
						y += lineSpace + textSize + 1
					} else if (megaSplit[0] == "lineNoSpace") {
						textXShift = 0
						y += textSize + 1
					} else if (megaSplit[0] == "bar") {
						card.drawImage(imgBar, cardWidth / 2 - imgBar.width / 2, y + textSize + lineSpace + 5)
						textXShift = 0
						y += 2 * lineSpace + textSize + 3
					} else if (megaSplit[0].toLowerCase() == "chaos") {
						//The chaos symbol (on planar cards) needs to be a bit bigger
						card.drawImage(manaSymbolImages[56], x + textXShift + textSize * 0.054, y + textSize * 0.17, textSize, manaSymbolImages[56].height * textSize / manaSymbolImages[56].width)
						textXShift += textSize * 1
					} else if (megaSplit[0] == "plane") {
						//This draws the large chaos symbol found on planar cards and permenantly shifts the text over
						card.drawImage(manaSymbolImages[57], x, y + 6, 48, 42)
						x += 58
					} else {
						//It's an image (mana symbol, tap, etc...)
						card.drawImage(manaSymbolImages[manaSymbolCode.indexOf(megaSplit[0].toLowerCase())], x + textXShift + textSize * 0.054, y + textSize * 0.075 + parseInt(document.getElementById("inputSymbolDown").value) + textBaselineShift * card.font.split("px")[0], textSize * 0.77, textSize * 0.77)
						textXShift += textSize * 0.84
					}
					if (megaSplit[1] != "") {
						plainWord = megaSplit[1] + " "
					} else if (splitIndex == splitWord.length - 1) {
						line += " "
					}
				} else {
					plainWord = splitWord[splitIndex]
				}
				if (plainWord != "") {
					//After isolating the plain word, write it!
					testLine = line + plainWord
					var lineWidth = card.measureText(testLine).width
					if (lineWidth + textXShift + x > tempTextWidth && wordIndex > 0) {
						//Word is too big
						card.fillText(line, x + textXShift, y + textBaselineShift * card.font.split("px")[0])
						line = plainWord
						y += textSize + 1
						textXShift = 0
					} else {
						//Word fits
						line = testLine
					}
					if (wordIndex + 1 == words.length) {
						card.fillText(line, x + textXShift, y + textBaselineShift * card.font.split("px")[0])
					}
				}
			}
		}
	}
	//Make things go back to normal :)
	card.textAlign="left"
}


//============================================//
//       Various website-related code         //
//============================================//
//Toggles the visibility of predetermined sections of the input boxes
function toggleView(targetId, targetClass) {
	for (var i = 0; i < document.getElementsByClassName(targetClass).length; i++) {
		document.getElementsByClassName(targetClass)[i].classList.remove("shown")
	}
	document.getElementById(targetClass + "-" + targetId).classList.add("shown")
}
//Randomizes the sample cards at the bottom of the page. Runs it here too
function randomizeSampleCards(count) {
	var cardNumbers = []
	while (cardNumbers.length < 3) {
		var randomNumber = Math.floor(Math.random() * count) + 1
		if (cardNumbers.indexOf(randomNumber) > -1) {
			continue
		}
		cardNumbers[cardNumbers.length] = randomNumber
		var imgName = "sampleCard" + cardNumbers.length
		window[imgName] = new Image()
		window[imgName].src = "sampleCards/sample-card-" + randomNumber + ".png"
	}
	sampleCard1.onload = function() {
		document.getElementById("sampleCardA").src = sampleCard1.src
	}
	sampleCard2.onload = function() {
		document.getElementById("sampleCardB").src = sampleCard2.src
	}
	sampleCard3.onload = function() {
		document.getElementById("sampleCardC").src = sampleCard3.src
	}
}


//============================================//
//              Image loading                 //
//============================================//
//Loads the set symbol from the gatherer site
function loadSetSymbol() {
	imgSetSymbol.cropped = false
	imgSetSymbol.src = "https://cors-anywhere.herokuapp.com/http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + document.getElementById("setSymbolCode").value.toUpperCase() + "&size=large&rarity=" + document.getElementById("setSymbolRarity").value.toUpperCase()
}
//Set Image to watermark!!!
function loadSetSymbolWatermark() {
	imgWatermark.whiteToTransparent = false
	imgWatermark.cropped = false
	imgWatermark.src = "https://cors-anywhere.herokuapp.com/http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + document.getElementById("inputWatermarkSetCode").value.toUpperCase() + "&size=large&rarity=C"
}
//Loads an image from URL
function imageURL(input, targetImage) {
	targetImage.cropped = false
	if (targetImage == imgWatermark) {
		imgWatermark.whiteToTransparent = false
	}
	targetImage.src = "https://cors-anywhere.herokuapp.com/" + input.value
}
function loadImage(event, destination, arg) {
	if (arg != false) {
		var input = event.target
		var reader = new FileReader()
		reader.onload = function() {
			var dataURL = reader.result
			destination.src = dataURL
			destination.cropped = false
			if (destination == imgWatermark) {
				imgWatermark.whiteToTransparent = false
			}
		}
		reader.readAsDataURL(input.files[0])
	}
}


//============================================//
//              Image Processing              //
//============================================//
Image.prototype.imgValues = function(x, y, w, h , otherImages) {
    this.imgX = x
    this.imgY = y
    this.imgW = w
    this.imgH = h
    if (otherImages != undefined) {
    	otherImageList = otherImages.split(",")
    	for (i = 0; i < otherImageList.length; i ++) {
    		otherImage = window[otherImageList[i]]
    		otherImage.imgX = x
  	  		otherImage.imgY = y
   			otherImage.imgW = w
    		otherImage.imgH = h
    	}
    }
}
var maskCanvas = document.createElement("canvas")
var maskContext = maskCanvas.getContext("2d")
CanvasRenderingContext2D.prototype.mask = function(masks, image, color) {
	if (image.imgX == undefined) {
		x = 0; y = 0; w = cardWidth; h = cardHeight;
	} else {
		x = image.imgX; y = image.imgY; w = image.imgW; h = image.imgH;
	}
    maskContext.clearRect(0, 0, cardWidth, cardHeight)
    var maskList = masks.split(";")
    for (var i = 0; i < maskList.length; i ++) {
        var currentMask = maskList[i].split(",")
        maskContext.globalCompositeOperation = currentMask[1]
        if (window[currentMask[0]] != undefined) {
            maskContext.drawImage(window[currentMask[0]], 0, 0, cardWidth, cardHeight)
        } else {
            maskContext.fillStyle = currentMask[0]
            maskContext.fillRect(0, 0, cardWidth, cardHeight)
        }
    }
    maskContext.globalCompositeOperation = "source-in"
    if (image != "none") {
    	maskContext.drawImage(image, x, y, w, h)
    }
    if (color != undefined) {
    	maskContext.fillStyle = color
        maskContext.fillRect(0, 0, cardWidth, cardHeight)
    }
    this.drawImage(maskCanvas, 0, 0, cardWidth, cardHeight)
}
//Create canvas for cropping the image
var cropCanvas = document.createElement("canvas")
var cropContext = cropCanvas.getContext("2d")
//Function that auto crops the image
function autocrop(url, destination) {
    //Create image, size canvas, draw image
    var imgTempSetSymbol = new Image()
    imgTempSetSymbol.crossOrigin = "anonymous"
    imgTempSetSymbol.src = url
    imgTempSetSymbol.onload = function() {
        if (imgTempSetSymbol.width > 0 && imgTempSetSymbol.height > 0) {
            cropCanvas.width = imgTempSetSymbol.width
            cropCanvas.height = imgTempSetSymbol.height
            cropContext.drawImage(imgTempSetSymbol, 0, 0)
            //declare variables
            var width = cropCanvas.width
            var height = cropCanvas.height
            var pix = {x:[], y:[]}
            var imageData = cropContext.getImageData(0,0,cropCanvas.width,cropCanvas.height)
            var x, y, index
            //Go through every pixel and
            for (y = 0; y < height; y++) {
                for (x = 0; x < width; x++) {
                    //(y * width + x) * 4 + 3 calculates the index at which the alpha value of the pixel at x, y is given
                    index = (y * width + x) * 4 + 3
                    if (imageData.data[index] > 0) {
                        //pix is the image object that stores two arrays of x and y coordinates. These stored coordinates are all the visible pixels
                        pix.x.push(x)
                        pix.y.push(y)
                    }
                }
            }
            //sorts the arrays numerically
            pix.x.sort(function(a,b){return a-b})
            pix.y.sort(function(a,b){return a-b})
            var n = pix.x.length - 1
            //Finds the difference between the leftmost and rightmost visible pixels, and the topmost and bottommost pixels, cuts out a section of the canvas
            width = pix.x[n] - pix.x[0]
            height = pix.y[n] - pix.y[0]
            var cropped = cropContext.getImageData(pix.x[0], pix.y[0], width + 1, height + 1)
            //Resizes the canvas and draws cropped image
            cropCanvas.width = width + 1
            cropCanvas.height = height + 1
            cropContext.putImageData(cropped, 0, 0)
            //Saves the newly cropped image to the given image
            destination.src = cropCanvas.toDataURL()
        }
    }
}
//Create a canvas to work on when making white pixels transparent
var transparentCanvas = document.createElement("canvas")
var transparentContext = transparentCanvas.getContext("2d")
//Function that auto  the image
function whiteToTransparent(targetImage) {
    //Create image, size canvas, draw image
    var imgTemporary = new Image()
    imgTemporary.crossOrigin = "anonymous"
    imgTemporary.src = targetImage.src
    imgTemporary.onload = function() {
    	if (imgTemporary.width > 0 && imgTemporary.height > 0) {
    		transparentCanvas.width = imgTemporary.width
    		transparentCanvas.height = imgTemporary.height
    		transparentContext.drawImage(imgTemporary, 0, 0)
            //declare variables
            var width = transparentCanvas.width
            var height = transparentCanvas.height
            var imageData = transparentContext.getImageData(0,0,transparentCanvas.width,transparentCanvas.height)
            var x, y, index
            //Go through every pixel and
            for (y = 0; y < height; y++) {
            	for (x = 0; x < width; x++) {
                    index = (y * width + x) * 4
                    if (imageData.data[index] >= 250 && imageData.data[index + 1] >= 250 && imageData.data[index + 2] >= 250) {
                        imageData.data[index + 3] = 0
                    }
                }
            }
            transparentContext.clearRect(0, 0, width, height)
            transparentContext.putImageData(imageData, 0, 0)
            targetImage.src = transparentCanvas.toDataURL()
        }
    }
}



//============================================//
//                  Other                     //
//============================================//
//loadColors("white-White,blue-Blue,colorlessLand-Colorless Land,gold-Gold"), this is an example of how to use the function
function loadColors(colors) {
	var endResult = ""
	var colorList = colors.split(",")
	for (var i = 0; i < colorList.length; i++) {
		endResult += "<option value='" + colorList[i].split("-")[0] + "'>" + colorList[i].split("-")[1] + "</option>"
	}
	document.getElementById("colorSelection").innerHTML = endResult
}
//Allows javascript files to be loaded through javascript code
function loadScript(scriptName){
	var script = document.createElement("script")
	script.setAttribute("type","text/javascript")
	script.setAttribute("src", scriptName)
	if (typeof script != "undefined") {
		document.getElementsByTagName("head")[0].appendChild(script)
	}
}
//Best for last - downloads the image!
function downloadCardImage(linkElement) {
	var cardImageData = canvas.toDataURL()
	if (cardImageData == undefined) {
		alert("Sorry, it seems that you cannot download your card. Please try using a different browser/device.")
	}
	linkElement.href = cardImageData
}


//============================================//
//                  Log it!                   //
//============================================//
console.log("The main.js file has finished loading.")
