// - - - - - - - - - - - - - - - - -
// File: light.cpp                  |
// Purpose: implements class Light  |
// Author: Taivo Lints, Estonia     |
// Date: May, 2003                  |
// Copyright: see copyright.txt     |
// - - - - - - - - - - - - - - - - -

#include "light.h"
#include "allegro.h"
using namespace std;

// - - - - - Class Light - - - - -

// ******************************
// * Construction & Destruction *
// ******************************

// - Light constructor - -
// Needs a pointer to the bitmap this light will "live" on.
// Also needs the start of 64 color gradient on palette.
Light::Light(BITMAP* inp_pArena, int inp_start_of_gradient) {

  radius = 64;

  x = 100;
  y = 100;

  speed_x = 1;
  speed_y = 1;

  start_of_gradient = inp_start_of_gradient;

  pArena = inp_pArena;
  pSprite = create_light_sprite();

  left_edge = static_cast<int>(x - radius);
  top_edge = static_cast<int>(y - radius);

  previous_radius = radius;

}

// - Light copy-constructor - -
Light::Light(const Light& rL) {

  radius = rL.radius;

  x = rL.x;
  y = rL.y;

  speed_x = rL.speed_x;
  speed_y = rL.speed_y;

  // Copy of light can currently live only on the same bitmap as original.
  pArena = rL.pArena;

  start_of_gradient = rL.start_of_gradient;

  // Must have its own light image.
  pSprite = create_light_sprite();

  left_edge = rL.left_edge;
  top_edge = rL.top_edge;

  previous_radius = rL.previous_radius;

}

// - Operator= overloading - -
Light& Light::operator=(const Light& rL) {

  if(&rL != this) {   // Check for self-assignment.

    radius = rL.radius;

    x = rL.x;
    y = rL.y;

    speed_x = rL.speed_x;
    speed_y = rL.speed_y;

    // Copy of light can currently live only on the same bitmap as original.
    pArena = rL.pArena;

    // Must have its own light image.
    pSprite = create_light_sprite();

    start_of_gradient = rL.start_of_gradient;

    left_edge = rL.left_edge;
    top_edge = rL.top_edge;

    previous_radius = rL.previous_radius;
  }

  return *this;

}

// - Light destructor - -
Light::~Light() {

  // Deletes light image (to prevent memory leak).
  destroy_bitmap(pSprite);

}


// *************
// * Functions *
// *************

// - Function: update - -
// Updates light position and size.
void Light::update() {

  // If radius has changed, then creates new image of light.
  if(radius != previous_radius) {
    destroy_bitmap(pSprite);
    pSprite = create_light_sprite();
    previous_radius = radius;
  }

  // Updates the position.
  x += speed_x;
  y += speed_y;


  // Bouncing against walls.
  if(x < 0) {
    x = 0;
    speed_x = -speed_x;
  }

  if(x > pArena->w) {
    x = pArena->w;
    speed_x = -speed_x;
  }

  if(y < 0) {
    y = 0;
    speed_y = -speed_y;
  }

  if(y > pArena->h) {
    y = pArena->h;
    speed_y = -speed_y;
  }

  // Updating some drawing related variables.
  left_edge = static_cast<int>(x - radius);
  top_edge = static_cast<int>(y - radius);

}

// - Function: draw - -
// Draws light on the bitmap.
void Light::draw() {

  draw_sprite(pArena, pSprite, left_edge, top_edge);

}


// *****************
// * Private stuff *
// *****************

// - Function: create_light_sprite - -
// Creates image of light with current radius and returns a pointer to it.
BITMAP* Light::create_light_sprite() {

  BITMAP* pLight_Sprite;

  // Creates a bitmap and clears it.
  pLight_Sprite = create_bitmap(2 * radius, 2 * radius);
  clear_bitmap(pLight_Sprite);

  // Fills it with light.
  for(int i = radius; i > 0; i--)
    circlefill(pLight_Sprite, radius - 1, radius - 1, i,
                 start_of_gradient + 64 * (radius - i) / radius);

  return pLight_Sprite;

}