/*
 *  Copyright (C) 2008 Kristian Kristola
 *
 *  This program is distributed under the terms of the
 *  GNU General Public License.
 *
 *  This file is part of Dave the Ordinary Spaceman.
 *
 *  Dave the Ordinary Spaceman 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 3 of the License, or (at your option) any later version.
 *
 *  Dave the Ordinary Spaceman 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 Dave the Ordinary Spaceman. If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */

#ifndef _GEENIMUTATOITUNEELLA_AASIANNORSULLA_MERIVUOKKO_EKSHIBITIOITUNA_
#define _GEENIMUTATOITUNEELLA_AASIANNORSULLA_MERIVUOKKO_EKSHIBITIOITUNA_

#include <string>
#include <map>
#include <SDL/SDL.h>
#include "level.h"
#include "teletext.h"
#include "analog_effects.h"
#include "editor.h"

using namespace std;

class Fellow;
class SDL_Surface;
class Scene;
class Remote;
class GLProgram;

class Game : public Effect
{
public:
  Game(bool disable_shaders, bool simple_shaders);
  ~Game();

  int run();
  Fellow *get_dave() const {return dave;}
  Fellow *get_dave_kuopio() const {return dave_kuopio;}
  Remote *get_remote() const {return remote;}
  float get_physics_time() const {return physics_time;}

  float get_capacity() const {return y_capacity;}
  float get_aspect_ratio() const {return (float)width/height;}
  const Vector &get_scroll() const {return scroll;}

  float scroll_fix_speed;
  float scroll_fix_depth;

  Level *get_current_level();

  struct Extensions {
    bool fbo;
    bool vbo;
    bool shaders;
    bool simple_shaders;
    bool gen_mipmap;
    bool antialias;
  };
  const Extensions *get_ext() const;
  float get_editor_anim() const;
  bool is_editor_shown() const {return show_editor;}
  float get_animation_speed() const {return animation_speed;}
  string get_level_filename() const;
  void switch_level(int num);
  float item_time() const {return 0.001f * SDL_GetTicks() - got_item_at;}
  void got_an_item() {this->got_item_at = 0.001f * SDL_GetTicks();}

private:
  float y_capacity;
  int width;
  int height;
  Vector scroll;
  bool handle();
  /*debug*/public:
    void render();private:
  inline bool sync() const;

  SDL_Surface *screen;
  float physics_time;
  float dt;
  map<string, Level *> levels;     // Kaikki kentät (tätä ei ehkä tarvita)
  bool running;                    // false jos peli lopetetaan, muuten true
  float quit_at;
  Level *current_level;            // Kenttä jossa ollaan
  Fellow *dave;                    // Oma pelaaja
  Fellow *dave_kuopio;
public:
  Teletext *text;                  // Testi teksti
private:

  // Effects
  Power          *poweron;
  Power          *poweroff;
  bool poweroff_on;
  bool poweron_on;
  Pixels2Cubes   *pixels2cubes;
  MotionBlur     *motion_blur;
  GaussianBlur   *gaussian_blur;
  TV             *tv;
  PalNoise       *noise;
  TapeDistortion *tape;

  Editor editor;
  bool show_editor;
  float editor_start_time;
  Extensions ext;
  Remote *remote;

  Image *img_rewind, *img_stop, *img_play, *img_record;
  int play_showed_for;
  float animation_speed;

  bool main_menu(bool fin);
  int page;          // Current page shown on the TV
  int page_num;      // Current page number shown at the top left corner
  int page_goal;     // The page the user wants to go to
  int page_final;    // The pageNNN.tv that is actually shown
  int digit;         // Which digit the user is entering ATM
  map<int, Teletext *> teletext;
  enum Action {NOTHING, STOP, START_GAME, QUIT};
  Action handle_teletext(SDL_Event *ev);
  struct Color
  {
    float r, g, b, a;
    float operator[](int i) const
    {
      return
	i==0 ? r :
	i==1 ? g :
	i==2 ? b : a;
    }
    operator float *() { return &r; }
    Color operator+(float x) const { return (Color){r+x, g+x, b+x, a}; }
  };
  map<char, Color> palette;

  void save_config() const;
  void load_config();
  map<string, string> config;
  int current_level_number;
  bool game_completed;
  bool credits;
  float got_item_at;

public:
  int get_current_level_number() const {return current_level_number;}
  float *chroma() const {return &motion_blur->chroma;}
  GLProgram *kuopio_prog;
  TV *get_tv() const {return tv;}
  GaussianBlur *get_gaussian() {return gaussian_blur;}
  bool showing_credits() const {return credits;}
  bool rendering_editor;
};

extern Game *game;

#endif
