/*   Copyright 2005,2006 Paweł Niegowski
*
*    This file is part of Fenrir.
*
*    Fenrir is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    Fenrir is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Fenrir; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "palette.h"
#include "map.h"
#include "main.h"
#include "play.h"
#include "sky.h"
#include "gui.h"
#include <string.h>
#include <allegro.h>
#define FADE_BITSHIFT 4

PALETTE base_palette;
PALETTE current_palette;
PALETTE backup_palette;
int cam_x = 0, cam_y = 0, cam_target_x = 0, cam_target_y = 0;
void (*event_func)() = 0;

RGB fade_color;
int fade_counter = 0;
bool fade_dir_in = false;
bool rot_palette = false;

void camera_think()
{
 static int x_mov, y_mov;
 x_mov = (cam_target_x - cam_x)/16;
 y_mov = (cam_target_y - cam_y)/16;
 cam_x += x_mov;
 cam_y += y_mov;
 if(cam_x < 0) cam_x = 0; if(cam_x >= map_w * 16 - buf->w) cam_x = map_w * 16 - buf->w - 1;
 if(cam_y < 0) cam_y = 0; if(cam_y >= map_h * 16 - buf->h) cam_y = map_h * 16 - buf->h - 1;
 rot_palette = true;
}

void palette_draw()
{
 if(rot_palette && fade_counter)
 {
  if(fade_dir_in)
  {
   for(int i=0; i<224; i++)
   {
    if(base_palette[i].r > current_palette[i].r)
     current_palette[i].r += ((base_palette[i].r - current_palette[i].r) >> FADE_BITSHIFT) + 1;
    else if(base_palette[i].r < current_palette[i].r)
     current_palette[i].r -= ((current_palette[i].r - base_palette[i].r) >> FADE_BITSHIFT) + 1;

    if(base_palette[i].g > current_palette[i].g)
      current_palette[i].g += ((base_palette[i].g - current_palette[i].g) >> FADE_BITSHIFT) + 1;
    else if(base_palette[i].g < current_palette[i].g)
      current_palette[i].g -= ((current_palette[i].g - base_palette[i].g) >> FADE_BITSHIFT) + 1;

    if(base_palette[i].b > current_palette[i].b)
     current_palette[i].b += ((base_palette[i].b - current_palette[i].b) >> FADE_BITSHIFT) + 1;
    else if(base_palette[i].b < current_palette[i].b)
     current_palette[i].b -= ((current_palette[i].b - base_palette[i].b) >> FADE_BITSHIFT) + 1;
   }
  }//fade_dir_in
  else
  {
   for(int i=0; i<224; i++)
   {
    if(fade_color.r > current_palette[i].r)
     current_palette[i].r += ((fade_color.r - current_palette[i].r) >> FADE_BITSHIFT) + 1;
    else if(fade_color.r < current_palette[i].r)
     current_palette[i].r -= ((current_palette[i].r - fade_color.r) >> FADE_BITSHIFT) + 1;

    if(fade_color.g > current_palette[i].g)
      current_palette[i].g += ((fade_color.g - current_palette[i].g) >> FADE_BITSHIFT) + 1;
    else if(fade_color.g < current_palette[i].g)
      current_palette[i].g -= ((current_palette[i].g - fade_color.g) >> FADE_BITSHIFT) + 1;

    if(fade_color.b > current_palette[i].b)
     current_palette[i].b += ((fade_color.b - current_palette[i].b) >> FADE_BITSHIFT) + 1;
    else if(fade_color.b < current_palette[i].b)
     current_palette[i].b -= ((current_palette[i].b - fade_color.b) >> FADE_BITSHIFT) + 1;
   }
  }//!fade_dir_in
  gui_loadpalette();
  set_palette(current_palette);
  vsynced = true;
  fade_counter--;
  rot_palette = false;
 }
 if(!fade_counter && !fade_dir_in && event_func)
 {
  event_func();
  event_func = 0;
 }
}

void palette_fade_in(RGB color, int l, bool fill)
{
 fade_color = color;
 fade_dir_in = true;
 fade_counter = l;
 if(fill)
  for(int i=0; i<224; i++)
  {
   current_palette[i].r = color.r;
   current_palette[i].g = color.g;
   current_palette[i].b = color.b;
  }
}

void palette_fade_out(RGB color, int l)
{
 fade_color = color;
 fade_dir_in = false;
 fade_counter = l;
}

void palette_set_fade(RGB color, float intensity)
{
 int start = 0, stop = 208;
 if(map_flags & MAPFLAGC_INDOOR)
 { start = 32; stop = 48; }
 for(int i = start; i < stop; i++)
 {
  base_palette[i].r = (char)(base_palette[i].r * (1-intensity) + color.r * intensity);
  base_palette[i].g = (char)(base_palette[i].g * (1-intensity) + color.g * intensity);
  base_palette[i].b = (char)(base_palette[i].b * (1-intensity) + color.b * intensity);
 }
}

void palette_set_multiply(RGB color, float intensity)
{
 int start = 0, stop = 208;
 if(map_flags & MAPFLAGC_INDOOR)
 { start = 32; stop = 48; }
 for(int i = start; i < stop; i++)
 {
  base_palette[i].r = (char)(base_palette[i].r * (1-intensity) + (base_palette[i].r*(color.r/63.0)) * intensity);
  base_palette[i].g = (char)(base_palette[i].g * (1-intensity) + (base_palette[i].g*(color.g/63.0)) * intensity);
  base_palette[i].b = (char)(base_palette[i].b * (1-intensity) + (base_palette[i].b*(color.b/63.0)) * intensity);
 }
}

void palette_set_backup()
{
 memcpy(backup_palette,base_palette,sizeof(RGB)*256);
}

void palette_restore()
{
 memcpy(base_palette,backup_palette,sizeof(RGB)*256);
}

//208: noon, 192: sunset, 176: night, 160: sunrise
void palette_interpolate_sky(int source, int dest, float intensity)
{
 for(int i = 0; i < 16; i++)
 {
  base_palette[208+i].r = (char)(sky_palette[source+i].r * (1-intensity) + sky_palette[dest+i].r * intensity);
  base_palette[208+i].g = (char)(sky_palette[source+i].g * (1-intensity) + sky_palette[dest+i].g * intensity);
  base_palette[208+i].b = (char)(sky_palette[source+i].b * (1-intensity) + sky_palette[dest+i].b * intensity);
 }
}

void palette_update_time()
{
 palette_restore();
 RGB night_col = { 12, 0, 63 };
 RGB sunrise_col = { 63, 63, 63 };
 RGB sunset_col = { 63, 30, 21 };
 //night/sunrise
 if(current_time < 64)
 {
  palette_set_fade(sunrise_col,0.125 - (64.0-current_time)/512.0);
  palette_set_multiply(night_col,(64.0-current_time)/96.0);
  palette_interpolate_sky(176,160,current_time/64.0);
 } else
 //sunrise/noon
 if(current_time < 128)
 {
  palette_set_fade(sunrise_col,0.125 - (current_time-64.0)/512.0);
  palette_interpolate_sky(160,208,current_time/64.0-1);
 } else
 //noon/sunset
 if(current_time < 196)
 {
  palette_set_multiply(sunset_col,(current_time-128)/64.0);
  palette_interpolate_sky(208,192,current_time/64.0-2);
 } else
 //sunset/night
 {
  palette_set_multiply(sunset_col,(256-current_time)/64.0);
  palette_set_multiply(night_col,(current_time-196)/96.0);
  palette_interpolate_sky(192,176,current_time/64.0-3);
 }
 if(!fade_counter)
 {
  memcpy(current_palette,base_palette,sizeof(RGB)*256);
  set_palette_range(current_palette,0,223,0);
 }
}
