//
//  Puck.m
//  AirHockey
//
//  Created by Górczyński Robert on 20/01/2012.
//

#import "Puck.h"

@implementation Puck

@synthesize maxSpeed, speed, dx, dy, winner;

- (id)initWithPuck:(UIView *)puck 
          Boundary:(CGRect)boundary 
             Goal1:(CGRect)goal1 
             Goal2:(CGRect)goal2 
          MaxSpeed:(float)max
{
    self = [super init];
    
    if (self) 
    {
        // Inicjalizacja prostokątów ograniczających.
        view = puck;
        rect[0] = boundary;
        rect[1] = goal1;
        rect[2] = goal2;
        maxSpeed = max;
    }
    return self;
}

- (void)dealloc
{
    [super dealloc];
}

// Wyzerowanie położenia początkowego.
- (void)reset
{
    // Wybór losowego położenia, w którym znajdzie się krążek.
    float x = rect[1].origin.x + arc4random() % ((int) rect[1].size.width);
    float y = rect[0].origin.x + rect[0].size.height / 2;    
    view.center = CGPointMake(x, y);
    
    box = 0;
    speed = 0;
    dx = 0;
    dy = 0;
    winner = 0;
}

- (CGPoint)center
{
    return view.center;
}

- (bool)animate
{
    // Jeżeli mamy zwycięzcę, animacja jest niepotrzebna.
    if (winner != 0) return false;
    
    bool hit = false;
    
    // Spowolnienie prędkości krążka ze względu na tarcie o boisko,
    // ale po pierwszym uderzeniu krążek nigdy nie może się zatrzymać.
    // W przeciwnym razie mamy gola.
    if (speed > 0)
    {
        speed = speed * 0.99;
        if (speed < 0.1) speed = 0.1;
    }
    
    // Przesunięcie krążka do nowego położenia na podstawie bieżącego kierunku i prędkości.
    CGPoint pos = CGPointMake(view.center.x + dx * speed,
                              view.center.y + dy * speed);
    
    // Sprawdzenie, czy krążek znajduje się w polu bramkowym.    
    if (box == 0 && CGRectContainsPoint(rect[1], pos))
    {
        // Krążek znajduje się w polu bramkowym gracza 1.
        box = 1;
    }
    else if (box == 0 && CGRectContainsPoint(rect[2], pos))
    {
        // Krążek znajduje się w polu bramkowym gracza 2.
        box = 2;
    }
    else if (CGRectContainsPoint(rect[box], pos) == false)
    {
        // Obsługa zderzeń ze ścianami w bieżącym prostokącie ograniczającym.
        if (view.center.x < rect[box].origin.x)
        {
            pos.x = rect[box].origin.x;
            dx = fabs(dx);
            hit = true;
        }
        else if (pos.x > rect[box].origin.x + rect[box].size.width)
        {
            pos.x = rect[box].origin.x + rect[box].size.width;
            dx = -fabs(dx);
            hit = true;
        }
        
        if (pos.y < rect[box].origin.y)
        {
            pos.y = rect[box].origin.y;
            dy = fabs(dy);
            hit = true;
            // Sprawdzenie pod kątem wygranej.
            if (box == 1) winner = 2;
        }
        else if (pos.y > rect[box].origin.y + rect[box].size.height)
        {
            pos.y = rect[box].origin.y + rect[box].size.height;
            dy = -fabs(dy);
            hit = true;
            // Sprawdzenie pod kątem wygranej.
            if (box == 2) winner = 1;
        }
    }
    
    // Umieszczenie krążka w nowym położeniu.
    view.center = pos;
    
    return hit;
}

// Sprawdzenie, czy wystąpiła kolizja z paletką i na tej podstawie zmiana ścieżki ruchu krążka.
- (bool)handleCollision:(Paddle *)paddle
{
    // Maksymalna odległość między krążkiem i paletką gwarantująca zderzenie to połowa 
    // średnicy paletki (64x64)=32 oraz krążka (40x40)=20, czyli 52.
    static float maxDistance = 52;
    
    // Pobranie bieżącej odległości od punktu centralnego prostokąta.
    float currentDistance = [paddle distance:view.center];
    
    // Sprawdzenie, czy doszło do kontaktu obiektów.
    if (currentDistance <= maxDistance)
    {
        // Zmiana kierunku ruchu krążka.
        dx = (view.center.x - paddle.center.x) / 32.0;
        dy = (view.center.y - paddle.center.y) / 32.0;
        
        // Dostosowanie prędkości krążka w celu odzwierciedlenia prędkości bieżącej i prędkości paletki.
        speed = 0.2 + speed / 2.0 + paddle.speed;
        
        // Ograniczenie prędkości maksymalnej.
        if (speed > maxSpeed) speed = maxSpeed;
        
        // Umieszczenie krążka w odległości większej niż promień paletki, aby zderzenie nie zostało wykryte po raz kolejny.
        float r = atan2(dy,dx);
        float x = paddle.center.x + cos(r) * (maxDistance+1);
        float y = paddle.center.y + sin(r) * (maxDistance+1);
        view.center = CGPointMake(x,y);
        
        return true;
    }
    
    return false;
}

@end
