/////////////////////////////
// advanced bitblt example //
/////////////////////////////
#include "ptc.h"






// image tile
struct TILE
{
    float x;               // current x position
    float y;               // current y position
    float cx;              // central x position
    float cy;              // central y position
    float dx;              // x movement phase shift
    float dy;              // y movement phase shift
    float sx;              // x movement amplitude multiplier
    float sy;              // y movement applitude multiplier
    float tx;              // x movement time multiplier
    float ty;              // y movement time multiplier
    Surface *surface;      // tile surface
};






int main(int argc,char *argv[])
{
    // initialize from command line
    PTC ptc(320,200,argc,argv);
    if (!ptc.ok())
    {
        // fallback to fuzzy32
        if (!ptc.Init(320,200))
        {
            // failure
            ptc.Close();
            cout << "could not initialize ptc\n";
            return 1;
        }
    }
    
    // load image
    Surface image(ptc,"../image.tga");
    image.Convert(ARGB8888);
    if (!image.ok())
    {
        ptc.Close();
        cout << "could not load image\n";
        return 1;
    }

    // locals
    int i=0;
    int x=0;
    int y=0;

    // initialize surface tiles
    TILE Tile[40];
    for (i=0,y=0; y<200; y+=40)
    {
        for (x=0; x<320; x+=40)
        {
            // create tile surface
            Tile[i].surface=new Surface(ptc,40,40,ARGB8888);
            if (!Tile[i].surface || !Tile[i].surface->ok())
            {
                // failure
                ptc.Close();
                cout << "failed to create tile surface\n";
                return 1;
            }

            // bitblt section of image to tile surface
            image.BitBlt(*Tile[i].surface,RECTANGLE(0,0,40,40),RECTANGLE(x,y,x+40,y+40));
        
            // setup tile parameters
            Tile[i].cx = x;
            Tile[i].cy = y;
            Tile[i].dx = random(1000) / 200.0f;
            Tile[i].dy = random(1000) / 200.0f;
            Tile[i].sx = random(1000) / 500.0f + 0.5f;
            Tile[i].sy = random(1000) / 700.0f + 0.5f;
            Tile[i].tx = random(1000) / 500.0f;
            Tile[i].ty = random(1000) / 500.0f;

            // next tile
            i++;
        }
    }

    // create drawing surface
    Surface surface(ptc,320,200,ARGB8888);

    // time
    float t  = 0.0f;
    float dt = 0.01;      // adjust for speed

    // main loop
    while (!ptc.kbhit())
    {
        // update tile positions
        for (int i=0; i<40; i++)
        {
            // tile energy
            float energy = 60.0f * ( sin( t*Tile[i].tx + Tile[i].dx) + 1.2 ) / 2.0f;
        
            // calculate current tile positions
            Tile[i].x = Tile[i].cx + ( energy * Tile[i].sx * sin( t*Tile[i].tx + Tile[i].dx ) ); 
            Tile[i].y = Tile[i].cy + ( energy * Tile[i].sy * sin( t*Tile[i].ty + Tile[i].dy ) ); 

            // draw tile to drawing surface
            Tile[i].surface->BitBlt(surface,Tile[i].x,Tile[i].y);
        }

        // update to display
        surface.Update();

        // clear drawing surface
        FORMAT format=surface.GetFormat();
        int bytes=surface.GetWidth()*format.bytes;
        int pitch=surface.GetPitch();
        int height=surface.GetHeight();
        char *buffer=(char*)surface.Lock();
        if (!buffer) return 1;
        for (int y=0; y<height; y++) memset(buffer+y*pitch,0,bytes);
        surface.Unlock();

        // time
        t+=dt;
    }
    return 0;
}
