#include "SnapFile.h"

using namespace std;

void SF_makeList( const string & indexName, vector<string> & dirList )
{
	// Stream
	ifstream myStream( indexName.c_str() );

	// Failure
	if ( !myStream )
	{
		cout << "SF_makeList can't read " << indexName << endl;
		return;
	}

	// Read
	string line;

	while( getline( myStream, line ) )
	{
		dirList.push_back( line );
	}

	// End
	myStream.close();
}


void SF_filter( vector<string> & dirList, string ext, bool autoRemove )
{
	// Setup
	unsigned int offset( ext.length() );
	unsigned int curLeng;
	vector<string> done;

	// Filtering
	while( !dirList.empty() )
	{
		curLeng = dirList.back().length();

		if ( dirList.back()[ curLeng - offset - 1] == '.'
		     && dirList.back().compare( curLeng - offset, offset, ext ) == 0 )
		{
			done.push_back( dirList.back() );

			if ( autoRemove )
				done.back().erase( curLeng - offset - 1, offset + 1 );
		}

		dirList.pop_back();
	}

	// Fill dirList again
	while( !done.empty() )
	{
		dirList.push_back( done.back() );

		done.pop_back();
	}
}


void SF_choose( const string & indexName, string & fileChosen, SDL_Surface* tgt, const SF_Graphic cfg )
{
	// Get file list
	vector<string> dirList;
	SF_makeList( indexName, dirList );

	if ( dirList.empty() )
	{
		cout << "SF_choose : no file found in " << indexName << "." << endl;
		return;
	} 

	// Graphic init
    bool mustDestroy;
    SDL_Surface* screen( tgt );
    mustDestroy = SF_fixWindow( screen, cfg );

    // Mecanism
    unsigned int select(0); // Element selected
    unsigned int top(0); // First element display (scroll)
    const unsigned int range( (screen->h - 32) / 9 );

    // Loop
    bool done(false);
    SDL_Event event;
    string msg("Jovian");
    while (!done)
    {
        // [4.1] Gestion évènements
        SDL_WaitEvent(&event);
        switch (event.type)
        {
        case SDL_QUIT:
            done = true;
            break;
        case SDL_KEYDOWN:
            switch( event.key.keysym.sym )
            {
            case SDLK_ESCAPE :
                done = true;
                break;
            case SDLK_SPACE:
            case SDLK_RETURN:
            	done = true;
            	fileChosen = dirList[ select ];
            	break;
            case SDLK_RIGHT :
            case SDLK_DOWN :
                if ( select < dirList.size() - 1 )
                	select ++;
                break;
            case SDLK_LEFT :
            case SDLK_UP :
                if ( select > 0 )
                	select --;
                break;
            default :
                break;
            }
            break;
        /*case SDL_MOUSEMOTION:
            mouse.x = event.motion.x ;
            mouse.y = event.motion.y ;
            break;*/
        default:
            break;

        }

        // Draw
        SDL_FillRect(screen, 0, cfg.color_back );

        SF_enhanceWindow( screen, cfg );

     	for ( unsigned int k( top ); k < dirList.size() && k < top + range; k++ )
     	{
     		if ( k == select )
     			stringColor( screen, 24, 32 + k*9, (">" + dirList[k]).c_str(), cfg.color_select );
     		else
     			stringColor( screen, 32, 32 + k*9, dirList[k].c_str(), cfg.color_line );
     	}

        SDL_Flip(screen);

    }

    // End
    if ( mustDestroy )
    {
        SDL_FreeSurface( screen );
        screen = nullptr;
    }

    return;
}


void SF_keyName( string & fileName, SDL_Surface* tgt, const SF_Graphic cfg )
{
	// Graphic init
    bool mustDestroy;
    SDL_Surface* screen( tgt );
    mustDestroy = SF_fixWindow( screen, cfg );

    // Input init
    SDL_EnableUNICODE( 1 );

    // Location
    const unsigned int y( screen->h / 2 - 4 );
    unsigned int x;

    // Loop
    bool done(false);
    SDL_Event event;
    while (!done)
    {
        // [4.1] Gestion évènements
        SDL_WaitEvent(&event);
        switch (event.type)
        {
        case SDL_QUIT:
            done = true;
            break;
        case SDL_KEYDOWN:
            switch( event.key.keysym.sym )
            {
            case SDLK_ESCAPE :
                done = true;
                fileName = "";
                break;
            case SDLK_RETURN :
            	done = true;
            	break;
            case SDLK_BACKSPACE :
            	if ( fileName.size() > 0 )
            		fileName.erase( fileName.size() - 1 );
            	break;
            case SDLK_RIGHT :
            case SDLK_DOWN :
                break;
            case SDLK_LEFT :
            case SDLK_UP :
                break;
            default :
            	if( event.key.keysym.unicode < 0x80 && event.key.keysym.unicode > 0 )
            	{
                	fileName += (char)event.key.keysym.unicode;
            	}
                break;
            }
            break;
        /*case SDL_MOUSEMOTION:
            mouse.x = event.motion.x ;
            mouse.y = event.motion.y ;
            break;*/
        default:
            break;

        }

        // Draw
        SDL_FillRect(screen, 0, cfg.color_back );

        SF_enhanceWindow( screen, cfg );

        x = screen->w / 2 - 4*fileName.length();
     	stringColor( screen, x, y, fileName.c_str(), cfg.color_select );

        SDL_Flip(screen);

    }

    // End
    if ( mustDestroy )
    {
        SDL_FreeSurface( screen );
        screen = nullptr;
    }
    
    return;
}

void SF_addAskedFile( const string & indexName, string & fileName, SDL_Surface* tgt, const SF_Graphic cfg )
{
	// Ask
    SF_keyName( fileName, tgt, cfg );

    // Add
    SF_addFile( indexName, fileName );
}

void SF_addFile( const string & indexName, const string & fileName )
{
    // Check occurence
    vector<string> dirList;
    SF_makeList( indexName, dirList );

    for ( auto it( dirList.begin() ); it != dirList.end(); it ++ )
    {
        if ( *it == fileName )
            return;
    }

    dirList.clear();

    // Stream
    ofstream myStream( indexName.c_str(), ios::app );

    // Failure
    if ( !myStream )
    {
        cout << "SF_makeList can't write " << indexName << endl;
        return;
    }

    // Write
    myStream << fileName << endl;

    // End
    myStream.close();
}

bool SF_fixWindow( SDL_Surface* & screen, const SF_Graphic cfg )
{
    // Surface already set
    if ( screen )
        return false;

    // Graphic init
    screen = SDL_SetVideoMode(cfg.w, cfg.h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF );
    if ( !screen )
    {
        cout << "SF_fixWindow : graphic error : " << SDL_GetError() << endl;
        return false;
    }
    SDL_WM_SetCaption( cfg.name.c_str(), 0);

    // Created
    return true;
}

void SF_enhanceWindow( SDL_Surface* screen, const SF_Graphic & cfg )
{
    unsigned int line_offset( 55 + 8 * cfg.name.length() );
    stringColor( screen, 50, 6, cfg.name.c_str(), cfg.color_line );
    #define SF_BORD 10
    lineColor( screen, SF_BORD, SF_BORD, 45, SF_BORD, cfg.color_line );
    lineColor( screen, line_offset, SF_BORD, screen->w - SF_BORD, SF_BORD, cfg.color_line );
    lineColor( screen, screen->w - SF_BORD, SF_BORD, screen->w - SF_BORD, screen->h - SF_BORD, cfg.color_line );
    lineColor( screen, screen->w - SF_BORD, screen->h - SF_BORD, SF_BORD, screen->h - SF_BORD, cfg.color_line );
    lineColor( screen, SF_BORD, screen->h - SF_BORD, SF_BORD, SF_BORD, cfg.color_line );
}