// HW uses a left-handed system, where X is to the right, Z is up, and Y is 
// forward when looking at the 300 marker on the Sensors Manager.
// In HW, rotation is counter-clockwise (e.g., in the opposite direction as 
// the the degree markers on the Sensors Manager pie-plate), when looking along 
// an axis toward the origin on the map.
// By default, all objects point along the positive X-axis.

var VersionInfo = '1.1'

function random(num)
{
	return Math.ceil(Math.random() * num)
}

function ellipseAdd(sResName, fPosX, fPosY, fPosZ, sLayout, sDistribution, fResources, iResType, fAxis1, fAxis2, fWidth, fHeight, iMode, iSteps, fTilt, fRotate, sProperties)	{
	var toRad = Math.PI / 180, toDeg = 180 / Math.PI
	fTilt *= toRad, fRotate *= toRad
	var theta = 0, arc = 360 * toRad / iSteps
	var volume = 0, resources = 0
	var cooX = 0, cooY = 0,	cooZ = 0
	var rotyX = 0, rotyY = 0, rotyZ = 0
	var rotzX = [], rotzY = [], rotzZ = []
	var endPointX = [], endPointY = []
	var outPointX = [], outPointY = []
	var midPointX = 0, midPointY = 0
	var edgePointX = 0, edgePointY = 0
	var lengthA = 0, lengthB = 0, lengthC = 0
	var widthA = 0, widthB = 0, widthC = 0
	var vectorX = 0, vectorY = 0, vectorZ = 0
	var vLength1 = 0, vLength2 = 0, vLength3 = 0
	var signY = 0, signZ = 0
	var angleY = 0, angleZ = 0
	var paramA = 0, paramB = 0, paramC = 0

	for (i = 0; i <= iSteps; i ++)
	{
		// generate the interior curve of the ellipse
		endPointX[i] = Math.cos(theta) * fAxis1
		endPointY[i] = Math.sin(theta) * fAxis2

		// generate the exterior curve of the ellipse, based on the mode
		// the modes are: uniform, confocalA and confocalB
		if (iMode == 0)
		{
			outPointX[i] = Math.cos(theta) * (fAxis1 + fWidth)
			outPointY[i] = Math.sin(theta) * (fAxis2 + fWidth)
		}
		else if (iMode == 1)
		{
			outPointX[i] = Math.cos(theta) * (fAxis1 + fWidth)
			outPointY[i] = Math.sin(theta) * Math.sqrt(Math.pow(fAxis1 + fWidth, 2) - Math.pow(fAxis1, 2) + Math.pow(fAxis2, 2))
		}
		else if (iMode == 2)
		{
			outPointX[i] = Math.cos(theta) * Math.sqrt(Math.pow(fAxis2 + fWidth, 2) + Math.pow(fAxis1, 2) - Math.pow(fAxis2, 2))
			outPointY[i] = Math.sin(theta) * (fAxis2 + fWidth)
		}

		theta += arc

		cooX = endPointX[i]
		cooY = endPointY[i]
		cooZ = 0

		// rotate around the y-axis if the shape is not rectangluar
		rotyX = cooX * Math.cos(fTilt)
		rotyY = cooY
		rotyZ = cooX * Math.sin(fTilt) * -1

		if (sLayout != 'Rectangle')
		{
			cooX = rotyX
			cooY = rotyY
			cooZ = rotyZ
		}

		// rotate around the z-axis
		rotzX[i] = Math.cos(fRotate) * cooX - Math.sin(fRotate) * cooY
		rotzY[i] = Math.sin(fRotate) * cooX + Math.cos(fRotate) * cooY
		rotzZ[i] = cooZ

		// calculate points for steps after the first
		if (i > 0)
		{
			// calculate midpoints for inner curve
			midPointX = (endPointX[i] + endPointX[i - 1]) / 2
			midPointY = (endPointY[i] + endPointY[i - 1]) / 2
			// calculate midpoints for outer curve
			edgePointX = (outPointX[i] + outPointX[i - 1]) / 2
			edgePointY = (outPointY[i] + outPointY[i - 1]) / 2
			// calculate scalar length for the outer curve
			lengthA = Math.pow(outPointX[i] - outPointX[i - 1], 2)
			lengthB = Math.pow(outPointY[i] - outPointY[i - 1], 2)
			lengthC = Math.sqrt(lengthA + lengthB)
			// calculate scalar width
			widthA = Math.pow(edgePointX - midPointX, 2)
			widthB = Math.pow(edgePointY - midPointY, 2)
			widthC = Math.sqrt(widthA + widthB)
			// calculate the coordinates for the tangent vector at the midpoints
			vectorX = rotzX[i] - rotzX[i - 1]
			vectorY = rotzY[i] - rotzY[i - 1]
			vectorZ = rotzZ[i] - rotzZ[i - 1]
			// calculate the length of the vector
			vLength1 = Math.sqrt(Math.pow(vectorX, 2) + Math.pow(vectorY, 2) + Math.pow(vectorZ, 2))
			// calculate the length of the vector projected onto the XY plane
			vLength2 = Math.sqrt(Math.pow(vectorX, 2) + Math.pow(vectorY, 2) + 0)
			// calculate the unit length of the x-component of the vector projected onto the XY plane
			vLength3 = vectorX / vLength2
			// calculate the unit length of the vector projected onto the XY plane, in the plane formed by it and the vector
			vLength4 = vLength2 / vLength1
			// determine the direction of the angles
			signY = vectorY / Math.abs(vectorY)
			signZ = vectorZ / Math.abs(vectorZ) * -1
			// calculate the rotation angles
			angleY = toDeg * Math.acos(vLength4) * signZ
			angleZ = toDeg * Math.acos(vLength3) * signY

			if (sLayout == 'Rectangle')
			{
				volume = lengthC * widthC * fHeight / 8
				paramA = lengthC / 2
				paramB = widthC / 2
				paramC = fHeight / 2
			}
			else if (sLayout == 'Cylinder')
			{
				volume = Math.pow(fWidth, 2) * Math.PI * fHeight
				paramA = fWidth
				paramB = lengthC
				paramC = angleY
			}
			else if (sLayout == 'Sphere')
			{
				volume = Math.pow(fWidth, 3) * Math.PI * 4 / 3
				paramA = fWidth
				paramB = 0
				paramC = angleY
			}

			if (iResType == 1)
			{
				resources *= volume
			}
			else
			{
				resources = fResources
			}

			RingWindow.document.write
			(
				'Resources ' + sResName + ', ' + Math.round(midPointX + fPosX) + ', ' + Math.round(midPointY + fPosY) + ', ' + Math.round(cooZ + fPosZ) + ', ' + sLayout + ', ' + sDistribution + ', ' + Math.round(resources) + ', ' + Math.round(paramA) + ', ' + Math.round(paramB) + ', ' + Math.round(paramC) + ', ' + Math.round(angleZ) + ', ' + sProperties + '\n'
			)
		}
	}
}

function branchAdd(sResName, fPosX, fPosY, fPosZ, sLayout, sDistribution, fResources, iResType, iNumDiv, iNumInt, iNumFrq, iNumBeg, iNumEnd, fRadius1, fRadius2, fLength1, fLength2, fAngle1, fAngle2, iMode, fTilt, fRotate, sProperties)	{
	var toRad = Math.PI / 180, toDeg = 180 / Math.PI
	fTilt *= toRad; fRotate *= toRad
	fAngle1 *= toRad; fAngle2 *= toRad
	var rotyX = 0, rotyY = 0, rotyZ = 0
	var rotzX = 0, rotzY = 0, rotzZ = 0
	var midPointX = 0, midPointY = 0, midPointZ = 0
	var paramA = 0,	paramB = 0
	var minRad = Math.min(fRadius1, fRadius2)
	var maxRad = Math.max(fRadius1, fRadius2)
	var minLen = Math.min(fLength1, fLength2)
	var maxLen = Math.max(fLength1, fLength2)
	var minAng = Math.min(fAngle1, fAngle2)
	var maxAng = Math.max(fAngle1, fAngle2)
	var iNumSeg = 0
	if (iNumBeg > 0)	iNumSeg = 1
	else if (iNumFrq > 0)	iNumSeg = iNumInt
	else if (iNumEnd > 0)	iNumSeg = 1
	for (i = 0; i < iNumSeg; i ++)
	{
		var rad = 0,	len = 0
		var angY = 0,	angZ = 0
		var randSgn1 = random(2),	randSgn2 = random(2)
		if (randSgn1 > 1)	randSgn1 = 1
		else	randSgn1 = -1
		if (randSgn2 > 1)	randSgn2 = 1
		else	randSgn2 = -1

		// if set to random mode
		if (iMode == 1)
		{
			rad = random(maxRad - minRad) + minRad
			len = random(maxLen - minLen) + minLen
			angY = randSgn1 * (random(maxAng - minAng) + minAng)
			angZ = randSgn2 * (random(maxAng - minAng) + minAng)
		}
		// if set to non-random mode
		else if (iMode == 0)
		{
			rad = maxRad
			len = maxLen
			angY = randSgn1 * maxAng
			angZ = randSgn2 * maxAng
		}

		fTilt += angY
		fRotate += angZ

		rotyX = Math.cos(fTilt) * len + Math.sin(fTilt) * 0
		rotyY = 0
		rotyZ = -1 * Math.sin(fTilt) * len + Math.cos(fTilt) * 0
		rotzX = Math.cos(fRotate) * rotyX - Math.sin(fRotate) * rotyY
		rotzY = Math.sin(fRotate) * rotyX + Math.cos(fRotate) * rotyY
		rotzZ = rotyZ

		midPointX = fPosX + rotzX / 2
		midPointY = fPosY + rotzY / 2
		midPointZ = fPosZ + rotzZ / 2

		if (sLayout == 'Cylinder')
		{
			volume = Math.pow(rad, 2) * Math.PI * len
			paramA = rad
			paramB = len
		}
		else if (sLayout == 'Sphere')
		{
			volume = Math.pow(rad, 3) * Math.PI * 4 / 3
			paramA = rad
			paramB = 0
		}

		volume = Math.pow(rad, 2) * Math.PI * len
		resources = fResources
		if (iResType == 1)
		{
			resources *= volume
		}

		RingWindow.document.write
		(
			'Resources ' + sResName + ', ' + Math.round(midPointX) + ', ' + Math.round(midPointY) + ', ' + Math.round(midPointZ) + ', ' + sLayout + ', ' + sDistribution + ', ' + Math.round(resources) + ', ' + Math.round(paramA) + ', ' + Math.round(paramB) + ', ' + Math.round(fTilt * toDeg) + ', ' + Math.round(fRotate * toDeg) + ', ' + sProperties +
			'\n'
		)

		fPosX += rotzX
		fPosY += rotzY
		fPosZ += rotzZ
	}
	if (iNumBeg > 0)
	{
		branchAdd(sResName, fPosX, fPosY, fPosZ, sLayout, sDistribution, fResources, iResType, iNumDiv, iNumInt, iNumFrq, (iNumBeg - 1), iNumEnd, fRadius1, fRadius2, fLength1, fLength2, fAngle1, fAngle2, iMode, fTilt, fRotate, sProperties)
	}
	else if (iNumFrq > 0)
	{
		for (j = 0; j < iNumDiv; j ++)
		{
			branchAdd(sResName, fPosX, fPosY, fPosZ, sLayout, sDistribution, fResources, iResType, iNumDiv, iNumInt, (iNumFrq - 1), 0, iNumEnd, fRadius1, fRadius2, fLength1, fLength2, fAngle1, fAngle2, iMode, fTilt, fRotate, sProperties)
		}
	}
	else if (iNumEnd > 0)
	{
		branchAdd(sResName, fPosX, fPosY, sLayout, fPosZ, sDistribution, fResources, iResType, 0, 0, 0, 0, (iNumEnd - 1), fRadius1, fRadius2, fLength1, fLength2, fAngle1, fAngle2, iMode, fTilt, fRotate, sProperties)
	}
}

function resourceWrite(kind)
{
	var branchVar = ['sResName', 'fPosX', 'fPosY', 'fPosZ', 'sLayout', 'sDistribution', 'fResources', 'iResType', 'iNumDiv', 'iNumInt', 'iNumFrq', 'iNumBeg', 'iNumEnd', 'fRadius1', 'fRadius2', 'fLength1', 'fLength2', 'fAngle1', 'fAngle2', 'iMode', 'fTilt', 'fRotate', 'sProperties']
	var ellipseVar = ['sResName', 'fPosX', 'fPosY', 'fPosZ', 'sLayout', 'sDistribution', 'fResources', 'iResType', 'fAxis1', 'fAxis2', 'fWidth', 'fHeight', 'iMode', 'iSteps', 'fTilt', 'fRotate', 'sProperties']
	var resourceVar = []
	var resourceStr = ''
	var stringEval = kind
	if (kind == 'ellipseAdd')	resourceVar = ellipseVar
	else if (kind == 'branchAdd')	resourceVar = branchVar
	if (typeof(RingWindow) == 'undefined')	RingWindow = window.open()
	else if (RingWindow.closed == true)	RingWindow = window.open()

	stringEval += '('
	for (i in resourceVar)
	{
		resourceStr += resourceVar[i] + ', '
		for (j = 0; j < (document.resourceForm.length - 2); j ++)
		{
			if (document.resourceForm[j].name == resourceVar[i])
			{
				if (document.resourceForm[j].name.substring(0, 1) == 's')
				{
					stringEval += '\'' + document.resourceForm[j].value + '\''
				}
				else
				{
					stringEval += document.resourceForm[j].value
				}
				stringEval += ','
			}
		}
	}
	resourceStr = resourceStr.slice(0, (resourceStr.length - 2))
	stringEval = stringEval.slice(0, (stringEval.length - 1))
	stringEval += ')'

	RingWindow.document.open()
	RingWindow.document.write
	(
		'<html><head><title>Resource Output</title><link rel="stylesheet" href="./style.css" type="text/css" /></head><body class="cen"><div class="lft"><pre>' +
		'; Generated using Homeworld Resource Maker v' + VersionInfo + ', by Mikail\n' +
		'; Created: ' + new Date() + '\n' +
		'; Key: ' + kind + '(' + resourceStr + ')\n' +
		'; Input: ' + stringEval + '\n' +
		'\n' +
		'; Resources type posx, posy, posz, Rectangle, distribution, numResources, length, width, height, rotz, properties...\n' +
		'; Resources type posx, posy, posz, Cylinder, distribution, numResources, radius, length, roty, rotz, properties...\n' +
		'; Resources type posx, posy, posz, Sphere, distribution, numResources, radius, nill, roty, rotz, properties...\n' +
		'\n'
	)

	eval(stringEval)
	RingWindow.document.write
	(
		'</pre></div></body></html>'
	)
	RingWindow.document.close()
}
