from unity import *

import ComponentUtil
import SteeringControl
import Steering
import PursuitRealism
import Propulsion
import WeaponController
import WeaponSystem
import Craft

import EventLog

import ClevernessUtil

from GetDistance import GetDistance

class AttackTarget(SteeringControl):
	def __init__(self, target):
		self.controller = False
		self.target = target
		# TODO Maybe pass in the target priority?
		self.steerInit("Attack "+target.name, 10)
		self.attackTimer = 0
		self.patience = 6
		self.tooCloseMeters = 150

		self.pursuit = PursuitRealism()
		self.pursuit.target = target.gameObject
		self.pursuit.leadImagination = Random.Range(-1.0, 1.0)
		self.pursuit.reactiveness = 0.8

		self.firing = 0

	def init(self):
		self.steering = ComponentUtil.findInLineage[Steering](self.gameObject)
		self.propulsion = ComponentUtil.findInLineage[Propulsion](self.gameObject)
		self.weaponController = ComponentUtil.findInLineage[WeaponController](self.gameObject)
		self.craft = ComponentUtil.findInLineage[Craft](self.gameObject)

	def step(self):
		if self.craft == None:
			self.controller.pop(self)
		if self.target == None:
			self.controller.pop(self)

		transform = self.gameObject.transform
		targetPosition = self.target.transform.position
		interceptPoint = targetPosition
		toTarget = targetPosition - transform.position
		targetDistance = toTarget.magnitude

		projectedTargetPosition = targetPosition

		if targetDistance < 900:
			projectedTargetPosition = ClevernessUtil.predictInterceptPoint(transform.position, \
					self.weaponController.currentSystem().ordinanceVelocity, self.target.gameObject)

		interceptPoint = self.pursuit.step(projectedTargetPosition, targetDistance)

		toProjectedPosition = projectedTargetPosition - transform.position
		projectedDistance  = toProjectedPosition.magnitude

		aoa = Vector3.Dot(transform.forward, toProjectedPosition.normalized)

		self.weaponController.chooseClosestWeapon(projectedDistance, aoa)

		if projectedDistance < 300:
			self.weaponController.setSync(WeaponSystem.SyncMode.SYNCED)
		elif projectedDistance < 600:
			self.weaponController.setSync(WeaponSystem.SyncMode.STAGGERED)
		else:
			self.weaponController.setSync(WeaponSystem.SyncMode.SEQUENT)

		self.firing -= Time.deltaTime

		if self.firing > 0:
			self.attackTimer = 0
			if self.weaponController.currentSystem().getOrdinanceCount() < 200:
				if self.craft.getIntelligence().countHoming(self.target.gameObject) > 1:
					self.weaponController.cycleWeapons()

			self.weaponController.fireActiveWeapon()
		else:
			Debug.DrawLine(transform.position, interceptPoint, Color(0, 1, 0, (aoa / 2) + .5))
			self.attackTimer += Time.deltaTime
			self.propulsion.setThrottle(1)

		self.controller.values["aoa"] = aoa

		if aoa > self.weaponController.currentSystem().effectiveAoa:
			if self.firing <= -1.5:
				Debug.DrawLine(transform.position, interceptPoint, Color(0, 1, 0, (aoa / 2) + .5));
				self.propulsion.setThrottle(.9)
				# self.firing = Mathf.Clamp01(projectedDistance / self.weaponController.activeRange()) < Random.Range(0.0, 1000) / 1000.0
				self.firing = Random.Range(1, 2)
				# TODO.. consult the flightgroup and see how much ordinance is on target..
		else:
			self.firing = 0

		if self.attackTimer > self.patience and projectedDistance < 400:
			self.propulsion.setThrottle(.75)
			self.controller.push(GetDistance(400))

		if targetDistance <= self.tooCloseMeters:
			self.propulsion.setThrottle(1)
			self.controller.push(GetDistance(600))

		self.steering.steerTowardsPoint(interceptPoint)

	def chooseWeapon(self):
		debls = self.target.gameObject.GetComponentsInChildren[Destructible]()
		damageToDestroy = sum([d.damageToDestroy() for d in debls])

		damageGoal = damageToDestroy / 3.0

		for i, weaponSystem in enumerate(self.weaponController.weaponSystems):
			if weaponSystem.potentialDamage() < damageGoal:
				pass
