#ifndef AA_AASAVER_H
#define AA_AASAVER_H

#include <tdescreensaver.h>
#include <tdeapplication.h>

#include <stdlib.h>

class Screen;
class Sprite;

/**
 * \mainpage Asciiquarium.
 *
 * \section intro Introduction
 *
 * Asciiquarium is a KDE screensaver to draw an ASCII art aquarium.  This is the
 * documentation of the API used in the program to generate the effect.  It should
 * be fairly simple, but basically:
 *
 * class AASaver is the main class, which handles outside events.  All of the
 * processing happens in the Screen class however, which manages a list of
 * Sprites, updating them and drawing them as needed.  When AASaver receives a
 * paintEvent(), it forwards it on to Screen to handle it.
 *
 * Each Sprite is composed of 1 or more Frames.  When a Screen wants a Sprite
 * to draw itself, the Sprite forwards the request to its currently shown Frame.
 *
 * The Frame is rectangular, and created from textual ASCII art, with a ASCII
 * art shape and color mask.  The mask is optional.  See aasaver.cpp for
 * examples for creating a Frame.
 *
 * The Frame supports transparency and colors, and will convert the textual data
 * into a TQPixmap representation on demand in order to reduce CPU load (at the
 * expense of a slight memory usage increase for each sprite).
 *
 * Screen handles the timing for the project, and at each timeout will call
 * Sprite::tickUpdate() from Screen::doAnimate().
 *
 * This whole program was inspired/copied from Kirk Baucom's asciiquarium
 * program, from http://www.robobunny.com/projects/asciiquarium/
 */

/**
 * The main class for the Asciiquarium screensaver.
 */
class AASaver: public KScreenSaver
{
    /// Handles the animation and drawing.
    Screen* screen;

public:
    /// Construct the screensaver with window id \p id.
    AASaver( WId id );

    /// Returns a random double between [0.0, limit).
    static double doubleRand(double limit)
    {
        return (limit * (static_cast<double>(TDEApplication::random()) / RAND_MAX));
    }

    /// Returns a random integer between [0, limit)
    static int intRand(int limit)
    {
        return TDEApplication::random() % limit;
    }

    /**
     * Returns a TQString holding a color mask, created by choosing random colors
     * to replace numbers in \p color_mask.
     */
    static TQString randColor(TQString color_mask);

    /// Adds the castle sprite to the screen.
    void addCastle();

    /// Adds the environment (sea, etc.) to the screen.
    void addEnvironment();

    /// Adds the seaweed to the screen.
    void addAllSeaweed();

    /// Adds the initial layout of fish to the sea, scaling the number of fish
    /// based on the current screen size.
    void addAllFish();

    /**
     * Adds a seaweed to a random position of the sea bottom.
     *
     * @param screen The Screen to add into.
     */
    static void addSeaweed(Screen* screen);

    /**
     * Returns a new fish sprite, which has not yet been added to a screen.
     *
     * @param screen The Screen to use when constructing the Sprite.
     * @todo Combine with addFish().
     */
    static Sprite *newFish(Screen *screen);
    
    /**
     * Adds a new fish sprite to \p screen.
     *
     * @param screen The Screen to add a fish to.
     */
    static void addFish(Screen *screen);

    /**
     * Adds a new air bubble sprite to \p screen.  The \p x, \p y, and \p z
     * coordinates are all in logical coordinates.
     *
     * @param screen The Screen to add the bubble to.
     * @param x The x position to start the bubble at.
     * @param y The y position to start the bubble at.
     * @param z The z position to start the bubble at.
     */
    static void addBubble(Screen* screen, int x, int y, int z);

    /**
     * Adds a Nessie, the Loch Ness Monster sprite to \p screen.
     *
     * @param screen The Screen to add Nessie to.
     */
    static void addNessie(Screen* screen);

    /**
     * Adds a big fish sprite to \p screen.
     *
     * @param screen The Screen to add the big fish to.
     */
    static void addBigFish(Screen* screen);

    /**
     * Adds a whale sprite to \p screen.
     *
     * @param screen The Screen to add the whale to.
     */
    static void addWhale(Screen* screen);

    /**
     * Adds a shark sprite to \p screen.  The shark can kill() fish it comes in
     * contact with (they will spawn more fish automatically).
     *
     * @param screen The Screen to add the shark to.
     */
    static void addShark(Screen* screen);

    /**
     * Adds a ship sprite to \p screen.
     *
     * @param screen The Screen to add the ship to.
     */
    static void addShip(Screen* screen);

    /**
     * Adds a random object from the set (Shark, Big Fish, Nessie, Whale, Ship)
     * to the sea.
     *
     * @param screen The Screen to add to.
     */
    static void addRandom(Screen* screen);

    /**
     * Reimplemented to update the widget when it gets dirty.
     */
    virtual void paintEvent(TQPaintEvent* pe);
};

#endif /* AA_AASAVER_H */
