package server

import (
	"log"

	v "hackerbots.us/vector"
)

// Projectile are the things robots can shoot at eachother.
type Projectile struct {
	Id       string    `json:"id"`
	Position v.Point2d `json:"position"`
	MoveTo   v.Point2d `json:"-"`
	Radius   int       `json:"-"`
	Speed    float64   `json:"-"`
	Damage   int       `json:"-"`
	Owner    *Robot    `json:"-"`
	Delta    float64
}

// Projectile.Tick is called every game tick and moves projectiles along,
// determines when they should blow up, and how damaage is propagated to
// players.
func (p *Projectile) Tick(g *Game) {
	vec := p.MoveTo.Sub(p.Position)
	v_norm := vec.Normalize()
	v_scaled := v_norm.Scale(p.Speed * p.Delta)
	newPos := p.Position.Add(v_scaled)

	hit_player := false
	for player := range g.players {
		for _, r := range player.Robots {
			if r == p.Owner {
				continue
			}

			player_rect := v.AASquareAtPoint(r.Position, 3)
			collision, _, _ := v.RectIntersection(player_rect, p.Position, v_scaled)
			if collision {
				hit_player = true
				p.Owner.gameStats.Hits++
				p.Owner.gameStats.DirectHits++

				if r.Health > 0 {
					// Direct hit causes more damage
					log.Printf("Direct Hit %v, Dmg:%v", r.Id, p.Damage)

					r.Health -= p.Damage
					r.Hit = true

					if r.Health <= 0 {
						r.gameStats.Deaths++
						p.Owner.gameStats.Kills++
					}
				}
			}
		}
	}

	// Are we going to intersect the destination zone in this tick?
	r_dest := v.AASquareAtPoint(p.MoveTo, 3.0)

	travel := newPos.Sub(p.Position)
	arrived, _, pos := v.RectIntersection(r_dest, p.Position, travel)

	if !arrived {
		for _, obj := range g.obstacles {
			collision, _, pos := v.RectIntersection(obj.Bounds, p.Position, travel)
			if collision {
				arrived = true
				if pos != nil {
					p.Position = *pos
				}
				obj.Hp -= p.Damage
				// if obj.Hp < 0 {
				// 	delete(g.obstacles, i)
				// }
			}
		}
	} else {
		if pos != nil {
			p.Position = *pos
		}
	}

	if arrived || hit_player {
		delete(g.projectiles, p)

		// Spawn a splosion
		splo := &Splosion{
			Id:       p.Id,
			Position: p.Position,
			Radius:   p.Radius,
			Lifespan: 8,
		}
		g.splosions[splo] = true

		for player := range g.players {
			for _, r := range player.Robots {
				dist := v.Distance(r.Position, p.Position)
				if dist < float64(p.Radius) {
					if r.Health > 0 {
						r.Health -= p.Damage
						r.Hit = true
					}
					p.Owner.gameStats.Hits++
					if r.Health <= 0 {
						r.gameStats.Deaths++
						if r == p.Owner {
							p.Owner.gameStats.Suicides++
						} else {
							p.Owner.gameStats.Kills++
						}
					}
				}
			}
		}
	} else {
		p.Position.X = newPos.X
		p.Position.Y = newPos.Y
	}
}
