/* main.c */

/****************************************************************************
 *
 *  Copyright (C) 2000-2001 Eli-Jean R. Leyssens, aka Pervect of Topix
 *
 *  This file is part of the CodePressor package.
 *
 *  CodePressor 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.
 *
 *  CodePressor 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 CodePressor; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 *
 *  Eli-Jean R. Leyssens can be reached via email at eli@dnd.utwente.nl
 *  snail: E-J.R. Leyssens, Schivelbeinerstr. 5, 10439 Berlin, Germany
 *
 ***************************************************************************/

#include <stdio.h>
#include <string.h>
#include <oslib/os.h>
#include <oslib/fileswitch.h>

#include "app.h"
#include "inputfile.h"
#include "outputfile.h"
#include "method0.h"
#include "method1.h"
#include "method2.h"
#include "method3.h"
#include "method4.h"
#include "method5.h"
#include "method6.h"
#include "method7.h"
#include "method8.h"

typedef bits(*PackFunction)(bool fSave);

#define METHODCOUNT 9

PackFunction arPackFunctions[ METHODCOUNT] = {
  Method0_Pack,
  Method1_Pack,
  Method2_Pack,
  Method3_Pack,
  Method4_Pack,
  Method5_Pack,
  Method6_Pack,
  Method7_Pack,
  Method8_Pack,
};

int main ( int argc, char ** argv) {
    int Method = -1;
    bits dwSize;
    bits dwBestSize;
    int BestMethod;
    bool fVerbose = TRUE;
    char szInput[ 1024];
    char szOutput[ 1024];
    void * argumentBuffer[ 1024];
    byte * pbInteger;
    byte * ram_limit;
    os_date_and_time * start;
    char * command;
    os_error * myerr;
    int spare;

    command = os_get_env( &ram_limit, &start);
    fprintf( stdout, "%s\n", command);
    myerr = xos_read_args( "/A,/G,/G,/E,h=H/S,v=V/S,q=Q/S", command, (char*) argumentBuffer, 1024 * sizeof( void *), &spare);
    if ( myerr != NULL) {
      fprintf( stderr, "ERROR [%s]\n", myerr->errmess);
      goto SyntaxError;
    }
    if ( argumentBuffer[ 4] != NULL) {
       /*
        * Display help
        */
        goto SyntaxError;
    }
    if ( argumentBuffer[ 5] != NULL) {
       /*
        * Display version number
        */
        fprintf( stdout, "%s %s (%s)\n", APP_NAME, APP_VERSION, APP_DATE);
        goto ReturnPoint;
    }
    if ( argumentBuffer[ 6] != NULL) {
       /*
        * Quiet
        */
        fVerbose = FALSE;
    }

    if ( ( argumentBuffer[ 1] == NULL) || ( argumentBuffer[ 2] == NULL)) {
      	if ( argumentBuffer[ 1]== NULL) {
            fprintf( stderr, "No input file given\n");
        }
        if ( argumentBuffer[ 2] == NULL) {
            fprintf( stderr, "No output file given\n");
        }
      	goto SyntaxError;
    }
    memset( szInput, 0, 1024);
    memcpy( szInput, (( os_gs*) argumentBuffer[ 1])->s, (( byte*) argumentBuffer[ 1])[0] | ( (( byte*) argumentBuffer[ 1])[1] << 8));
    memset( szOutput, 0, 1024);
    memcpy( szOutput, (( os_gs*) argumentBuffer[ 2])->s, (( byte*) argumentBuffer[ 2])[0] | ( (( byte*) argumentBuffer[ 2])[1] << 8));

    if ( argumentBuffer[ 3] == NULL) {
      	/*
      	 * No method given, so try all methods
      	 */
        Method = -1;
    } else {
      	pbInteger = ((os_gi *) argumentBuffer[ 3])->i;
      	Method = pbInteger[ 0] | ( pbInteger[ 1] << 8) | ( pbInteger[ 2] << 16) | ( pbInteger[ 3] << 24);
        if (( Method < 0) || ( Method >= METHODCOUNT)) {
            fprintf( stderr, "Invalid method value [%d]\n", Method);
            goto SyntaxError;
        }
    }

    SetOutputFile( szOutput);
    if ( !ReadInputFile( szInput) ) {
	printf( "ReadInputFile failed for [%s]\n", szInput);
    }

    if ( Method < 0) {
      dwBestSize = 0xffffffff;
      BestMethod = -1;
      if ( fVerbose) {
         fprintf( stdout, "Trying all methods for [%s], original size %d\n", szInput, InputSize);
      }
      for ( Method = 0 ; Method < METHODCOUNT ; Method++) {
          dwSize = arPackFunctions[ Method]( FALSE);
          if ( dwSize == 0) {
             fprintf( stderr, "Method%d_Pack failed for [%s]\n", Method, szInput);
          } else {
             if ( fVerbose) {
                 fprintf( stdout, "  Method %1d: %d\n", Method, dwSize);
             }
             if ( dwSize < dwBestSize) {
               dwBestSize = dwSize;
               BestMethod = Method;
             }
          }
      }
      if ( BestMethod < 0) {
        fprintf( stderr, "All methods failed for [%s]\n", szInput);
        goto ReturnError;
      } else {
        if ( fVerbose) {
            fprintf( stdout, "Best method = %d\n", BestMethod);
        }
        Method = BestMethod;
      }
    }

    dwSize = arPackFunctions[ Method]( TRUE);
    if ( dwSize == 0) {
       fprintf( stderr, "Method%d_Pack failed for [%s]\n", Method, szInput);
       goto ReturnError;
    }
    if ( dwSize > InputSize) {
       fprintf( stderr, "Warning: resulting file is bigger than original!\n");
    }

    if ( fVerbose) {
       fprintf( stdout, "Packed [%s] from %d to %d bytes (%2.1f%%)\n\n", szInput, InputSize, dwSize, 100 * ((double) dwSize )/ (( double) InputSize));
    }

ReturnPoint:
    return 0;


SyntaxError:
    fprintf( stderr, "Syntax: %s [options] <input> <output> [<method>]\n", argv[ 0]);
    fprintf( stderr, "\tmethod = 0..%d Try all methods if not specified\n", ( METHODCOUNT - 1));
    fprintf( stderr, "\toptions:\n");
    fprintf( stderr, "\t\t-h\tHelp, display this help text\n");
    fprintf( stderr, "\t\t-v\tVersion, display version information\n");
    fprintf( stderr, "\t\t-q\tQuiet, suppress informational messages\n");
ReturnError:
    return 1;
}
