#ifdef WINDOWS
#define ZLIB_WINAPI
#include <windows.h>
char outdir[] = "out_data\\";
#else
char outdir[] = "out_data/";
#endif

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#ifndef MAX_PATH
#define MAX_PATH 256
#endif

void Strip( char* p )
{
    char* q;

    q = strstr( p, "//" );

    if ( q != NULL )
        *q = 0;

    q = p + strlen( p ) - 1;

    while ( p <= q ) {
        if ( ! ( isspace( *q ) || *q == '\n' || *q == '\r' ) )
            break;
        *q-- = 0;
    }
}


int run( char* dir, char* base, char* p1, char* p2 )
{
    char buffer[ 512 ];
    if ( *dir ) {
        strcpy( buffer, dir );
#ifdef WINDOWS
        strcat( buffer, "\\" );
#else
        strcat( buffer, "/" );
#endif
    }
    else {
        *buffer = 0;
    }
    sprintf( buffer + strlen( buffer ), base, p1, p2 );
    fprintf( stderr, "Running: %s\n", buffer );
    return system( buffer );
}


int svg2bmp( char* svg, char* bmp )
{
    int r;
    if ( run( "", "java -jar batik-1.6/batik-rasterizer.jar -d temp.png \"%s\"", svg, "" ) )
        return 1;
    unlink( bmp );
    r = run( "bin", "png2bmp -o \"%s\" temp.png", bmp, "" );
    unlink( "temp.png" );
    return r;
}


#ifdef WINDOWS
int getname(char *s)
{
int r;
OPENFILENAME ofn;
*s=0;
ZeroMemory(&ofn, sizeof(OPENFILENAME));

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = s;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "Keyboard descriptions\0*.txt\0All files\0*.*\0";
ofn.lpstrTitle = "Select keyboard description file";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
return GetOpenFileName(&ofn);
}


int getsavename(char *s)
{
int r;
OPENFILENAME ofn;
//*s=0;
ZeroMemory(&ofn, sizeof(OPENFILENAME));

ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = NULL;
ofn.lpstrFile = s;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = "Palm skin files (.prc)\0*.prc\0";
ofn.lpstrTitle = "Save output file as";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
return GetSaveFileName(&ofn);
}
#endif



int DupFile( char* src, char* dest )
{
    FILE* in;
    FILE* out;
    int   c;
    
    fprintf( stderr, "Copying %s -> %s.\n", src, dest );

    in = fopen( src, "r" );
    if ( in == NULL )
        return 1;
    out = fopen( dest, "wb" );
    if ( out == NULL ) {
        fclose( out );
        return 2;
    }

    while( -1 != ( c = fgetc( in ) ) ) {
        fputc( c, out );
    }

    fputc( 0, out );

    fclose( in );
    fclose( out );

    return 0;
}



void DumpFile( FILE* in, char* name )
{
    FILE* out;
    static char buffer[ 30000 ];

    out = fopen( name, "wb" );

    while ( NULL != fgets( buffer, 30000, in ) ) {
        Strip( buffer );

        if ( ! strcmp( buffer, ":END" ) )
            break;

        if ( out != NULL ) {
            fputs( buffer, out );
            fputc( '\n', out );
        }    
    }

    if ( out != NULL )
        fputc( 0, out );

    fclose( out );
}


int isdivider( char c )
{
    switch ( c ) {
        case '/':
        case '\\':
        case ':':
            return 1;
        default:
            return 0;
    }
}



void chtodir( char* s )
{
    char* t = s + strlen( s ) - 1;
    char dirname[ 512 ];

    while ( s <= t ) {
        if ( isdivider( *t ) ) {
             strncpy( dirname, s, t - s + 1 );
             dirname[ t - s + 1 ] = 0;
             chdir( dirname );
             break;
        }
        t--;
    }
}



main( int argc, char** argv )
{
    char buffer[ 256 ];
    char filename[ MAX_PATH + 1 + 4 ] = "GenericKeyboard.prc";
    char palmname[ 32 ] = "Generic Keyboard";
    char inname[ MAX_PATH + 1 ] = "";
    FILE* f;
    int  haveHelp = 0;
    int  haveCycling = 0;
    int  haveCase = 0;

    if ( argc <= 1 ) {
#ifdef WINDOWS
        if ( ! getname ( inname ) )
#endif
            return 1;

    }
    else {
        strncpy( inname, argv[ 1 ], 255 );
        inname[ 255 ] = 0;
    }
    f = fopen( inname, "r" );
    if ( f == NULL ) {
        fprintf( stderr, "%s not found.\n", inname );
        return 7;
    }

    chtodir( argv[ 0 ] );

    while ( NULL != fgets( buffer, 256, f ) ) {
        Strip( buffer );

        if ( ! strcmp( buffer, "FILENAME:" ) ) {
            if ( NULL != fgets( buffer, 256, f ) ) {
                Strip( buffer );
                strncpy( filename, buffer, 255 );
                filename[ 255 ] = 0;
            }
        }
        else if ( ! strcmp( buffer, "PALM-NAME:" ) ) {
            if ( NULL != fgets( buffer, 32, f ) ) {
                Strip( buffer );
                strncpy( palmname, buffer, 31 );
                palmname[ 31 ] = 0;
            }
        }
        else if ( ! strcmp( buffer, "SKIN-HELP:" ) ) {
            DumpFile( f, "out_data/SkinHelp.txt" );
            haveHelp = 1;
        }
        else if ( ! strcmp( buffer, "CYCLING:" ) )  {
            DumpFile( f, "out_data/Cycling.txt" );
            haveCycling = 1;
        }
        else if ( ! strcmp( buffer, "CAPITALIZATION:" ) ) {
            DumpFile( f, "out_data/CharacterCase.txt" );
            haveCase = 1;
        }
    }

    fclose( f );

#ifdef WINDOWS
    if ( 1 == argc ) {
        if ( ! getsavename( filename ) )
            return 1;
        if ( strlen( filename ) < 4 || stricmp( filename + strlen( filename ) - 4, ".prc" ) ) {
            strcat( filename, ".prc" );
        }
    }
#endif

    chtodir( argv[ 0 ] );

    if ( ( ! haveHelp && DupFile( "standard_data/SkinHelp.txt", "out_data/SkinHelp.txt" ) ) ||
         ( ! haveCycling && DupFile( "standard_data/Cycling.txt", "out_data/Cycling.txt" ) ) ||
         ( ! haveCase && DupFile( "standard_data/CharacterCase.txt", "out_data/CharacterCase.txt" ) ) ||
         run( "bin", "makegrid scu \"g:%s\" > %sPortrait.svg", inname, outdir ) ||
         svg2bmp( "out_data/Portrait.svg", "out_data/Portrait.bmp" ) ||
         run( "bin", "makegrid rscu \"g:%s\" > %sLandscape.svg", inname, outdir ) ||
         svg2bmp( "out_data/Landscape.svg", "out_data/Landscape.bmp" ) ||
         run( "bin", "makegrid i \"g:%s\" > %sPortrait-map.svg", inname, outdir ) ||
         svg2bmp( "out_data/Portrait-map.svg", "out_data/Portrait-map.bmp" ) ||
         run( "bin", "makegrid ri \"g:%s\" > %sLandscape-map.svg", inname, outdir ) ||
         svg2bmp( "out_data/Landscape-map.svg", "out_data/Landscape-map.bmp" ) ||
         run( "bin", "bmp2abmp8 -f \"%sPortrait-map.bmp\" \"%sPortrait-map.bin\"", outdir, outdir ) ||
         run( "bin", "bmp2abmp8 -f \"%sLandscape-map.bmp\" \"%sLandscape-map.bin\"", outdir, outdir ) ||
         run( "bin", "pilrc -ro -LE32 -SonySkin -type rsrc -creator T3sk -name \"%s\" -o \"%s\" standard_data/hexkey.rcp", palmname, filename ) ||
         run( "bin", "zipDB -n \"%s\"", filename, "" ) ) {
        fprintf(stderr, "Error generating keyboard.\n" );
        return 4;
    }

    return 0;
}
