// ---------------------------------------------------------------------------
// 
//   Lily Engine alpha
// 
//   Copyright (c) 2010 Clifford Jolly
//     http://cliffjolly.com
//     cliff@cliffjolly.com
// 
// ---------------------------------------------------------------------------
// 
//   This program 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.
//  
//   This program 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 this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
//   USA
// -------------------------- END HEADER -------------------------------------

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <SDL/SDL.h>

#include "../image/image.h"
#include "../filesystem/filesystem.h"

SDL_Surface *loadImage(const std::string &fileName) {

    int fileLength = 0;
    char *tgaBuf = FileSystem::loadFile(fileName, &fileLength);

    if(!tgaBuf) {
        cout << "Couldn't load the file!" << endl;
        return NULL;
    }

    static Image *img = NULL;
    static SDL_Surface *surf = NULL;

    if(surf) {
        delete surf;
        surf = NULL;
    }

    if(img) {
        delete img;
        img = NULL;
    }

    if(tgaBuf) {
        img = loadTGA(tgaBuf, fileLength);
        delete[] tgaBuf;
        if(img) {
            surf = img->createSurface();
        }
    }

    return surf;
}

time_t getLastModTime(const std::string &fileName) {

    struct stat statBuf = {0};

    stat(fileName.c_str(), &statBuf);

    return statBuf.st_mtime;

}

void drawSprite(SDL_Surface *surf, SDL_Surface *screen, int tileSize, int srcx, int srcy, int dstx, int dsty) {

    SDL_Rect dstRect;
                
    dstRect.x = tileSize * dstx;
    dstRect.y = tileSize * dsty;
    dstRect.w = tileSize;
    dstRect.h = tileSize;

    SDL_Rect srcRect;
                
    srcRect.x = tileSize * srcx;
    srcRect.y = tileSize * srcy;
    srcRect.w = tileSize;
    srcRect.h = tileSize;

    SDL_BlitSurface(surf, &srcRect, screen, &dstRect);
}

int main(int argc, char *argv[]) {

    if(argc < 2) {
        cout << "Usage: " << argv[0] <<
            "\n  <TGA file to watch>" <<
            "\n  [tile size (32)]" <<
            "\n  [tile slot x (0)]" <<
            "\n  [tile slot y (0)]" <<
            "\n  [region of tiles it has to connect to left]" <<
            "\n  [region of tiles it has to connect to top]" <<
            "\n  [region of tiles it has to connect to right]" <<
            "\n  [region of tiles it has to connect to bottom]" <<
            endl;
        return 1;
    }
    
    string fileName = argv[1];
    int tileSize = 32;
    int tilex = 0;
    int tiley = 0;

    int regionTop = 0;
    int regionBottom = 2;
    int regionLeft = 0;
    int regionRight = 2;

    if(argc > 2) tileSize = atoi(argv[2]);
    if(argc > 3) tilex = atoi(argv[3]);
    if(argc > 4) tiley = atoi(argv[4]);

    if(argc > 5) regionLeft = atoi(argv[5]);
    if(argc > 6) regionTop = atoi(argv[6]);
    if(argc > 7) regionRight = atoi(argv[7]);
    if(argc > 8) regionBottom = atoi(argv[8]);

    int regionW = (regionRight - regionLeft) + 1;
    int regionH = (regionBottom - regionTop) + 1;

    SDL_Init(SDL_INIT_VIDEO);

    SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, 0);

    SDL_Surface *surf = loadImage(fileName);
    
    if(!surf) return 1;

    bool quit = false;
    bool redraw = true;
    
    time_t lastModTime = getLastModTime(fileName);

    while(!quit) {
        
        while(!quit && !redraw) {

            SDL_Event event;
            SDL_PollEvent(&event);
            switch(event.type) {

            case SDL_QUIT:
                quit = true;
                break;

            default:
                break;

            }

            int newModTime = getLastModTime(fileName);
            if(newModTime != lastModTime) {
                cout << "Refreshing image" << endl;
                lastModTime = newModTime;
                surf = loadImage(fileName);
                while(!surf) {
                    surf = loadImage(fileName);
                }
                redraw = true;
            }
         
            SDL_Delay(1);
        }

        if(surf) {

            // Draw sprite surrounded by itself.
            for(int x = 0; x < 3; x++) {
                for(int y = 0; y < 3; y++) {
                    drawSprite(surf, screen, tileSize, tilex, tiley, x, y);
                }
            }

            for(int i = 0; i < regionW * regionH; i++) {

                int regionCol = (i % regionW) + regionLeft;
                int regionRow = (i / regionW) + regionTop;

                int drawCol = i % 4;
                int drawRow = i / 4;

                int drawOffsetX = (drawCol * 3) + 3;
                int drawOffsetY = (drawRow * 3);

                for(int x = 0; x < 3; x++) {
                    for(int y = 0; y < 3; y++) {
                        if(x == 1 && y == 1) {

                            // Draw the sprite at the center.
                            drawSprite(surf, screen, tileSize,
                                       tilex, tiley, drawOffsetX + x, drawOffsetY + y);
                        } else {

                            // Draw whatever sprite from the region.
                            drawSprite(surf, screen, tileSize,
                                       regionCol, regionRow, drawOffsetX + x, drawOffsetY + y);
                        }
                    }
                }

            }


            redraw = false;

            SDL_Flip(screen);
        }
    }



    SDL_Quit();
    

    return 0;
}
