/* This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want
 * To Public License, Version 2, as published by Sam Hocevar. See
 * http://sam.zoy.org/wtfpl/COPYING for more details. */ 

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

#include "../../satcom_lib/sc_common.h"


int main (int argc, char *argv[])
{
    if(argc <= 1)
    {
        printf("Type %s -h for help.\n", argv[0]);
        return 0;
    }
    if(argc >= 2)
    {
        if((!strcmp(argv[1], "-h"))
        || (!strcmp(argv[1], "-help"))
        || (!strcmp(argv[1], "-?")))
        {
            printf("--- COMP v0.3 by cafe-alpha.                                ---\n");
            printf("--- This is a part of my entry in the S.A.T.U.R.N. contest. ---\n");
            printf("Note: uses LibLZF: http://oldhome.schmorp.de/marc/liblzf.html\n");
            printf("Usage : -c <in_file> <out_file>       -> Compress\n");
            printf("        -d <in_file> <out_file>       -> Decompress\n");
            printf("        -t <sz_stt> <sz_end> <sz_cnt> -> Test comp->decomp\n");
            return 0;
        }
    }


    if(!strcmp(argv[1], "-c"))
    {
        if(argc != 4) return 1;
        char* infile  = argv[2];
        char* outfile = argv[3];

        unsigned long len, i, j;
        unsigned char* buffer1 =NULL;
        unsigned char* buffer2 =NULL;
        FILE* fp;

        fp = fopen(infile, "rb");
        if(fp)
        {
            fseek(fp, 0, SEEK_END);
            len = ftell(fp);
            fseek(fp, 0, SEEK_SET);

            buffer1 = (unsigned char*)malloc(len);
            if(!buffer1)
            {
                fclose(fp); fp = NULL;
                printf("Alloc error !\n");
                return 1;
            }

            fread(buffer1, 1, len, fp);
            fclose(fp); fp = NULL;

            buffer2 = (unsigned char*)malloc(len+SC_COMP_HEADER_MAXSIZE);
            if(!buffer2)
            {
                free(buffer1); buffer1 = NULL;
                printf("Alloc error !\n");
                return 1;
            }
        }

        unsigned long ret = comp_exec(buffer1, len, buffer2);
        printf("Compressed size = %d bytes (input size * %f %%)\n", ret, ((float)(100*ret))/len);
        fp = fopen(outfile, "wb");
        if(fp)
        {
            fwrite(buffer2, 1, ret, fp);
            fclose(fp); fp = NULL;
        }

        free(buffer2); buffer2 = NULL;
        free(buffer1); buffer1 = NULL;

    }
    else if(!strcmp(argv[1], "-d"))
    {
        if(argc != 4) return 1;
        char* infile  = argv[2];
        char* outfile = argv[3];

        unsigned long len, decomplen, i, j;
        unsigned char* buffer1 =NULL;
        unsigned char* buffer2 =NULL;
        FILE* fp;

        fp = fopen(infile, "rb");
        if(fp)
        {
            fseek(fp, 0, SEEK_END);
            len = ftell(fp);
            fseek(fp, 0, SEEK_SET);

            buffer1 = (unsigned char*)malloc(len);
            if(!buffer1)
            {
                fclose(fp); fp = NULL;
                printf("Alloc error !\n");
                return 1;
            }

            fread(buffer1, 1, len, fp);
            fclose(fp); fp = NULL;

            decomplen = decomp_getsize(buffer1, len);
            buffer2 = (unsigned char*)malloc(decomplen);
            if(!buffer2)
            {
                free(buffer1); buffer1 = NULL;
                printf("Alloc error !\n");
                return 1;
            }
        }

        unsigned long ret = decomp_exec(buffer1, len, buffer2);
        printf("DeCompressed size = %d bytes\n", ret);
        fp = fopen(outfile, "wb");
        if(fp)
        {
            fwrite(buffer2, 1, ret, fp);
            fclose(fp); fp = NULL;
        }

        free(buffer2); buffer2 = NULL;
        free(buffer1); buffer1 = NULL;
    }
    else if(!strcmp(argv[1], "-t"))
    {
        if(argc != 5) return 1;
        unsigned long sz_stt = atoi(argv[2]);
        unsigned long sz_end = atoi(argv[3]);
        unsigned long sz_cnt = atoi(argv[4]);

//printf("stt=%d, end=%d, cnt=%d\n", sz_stt, sz_end, sz_cnt);
//return 1;
        unsigned long i, j, k;
        srand(time(NULL));

        for(i=sz_stt; i<=sz_end; i++)
        {
            for(j=0; j<=sz_cnt; j++)
            {
#define TBUFF_SIZE 65536
                unsigned char buffer1[TBUFF_SIZE];
                unsigned char buffer2[TBUFF_SIZE];
                unsigned char buffer3[TBUFF_SIZE];
                memset((void*)buffer2, 0, TBUFF_SIZE);
                memset((void*)buffer1, 0, TBUFF_SIZE);
                memset((void*)buffer3, 0, TBUFF_SIZE);
                /* Fill input buffer with random data. */
                unsigned long size1, size2, size3;
                size1 = i;
                unsigned char cprev = 0;
                for(k=0; k<size1; k++)
                {
                    unsigned char c;
                    if((rand()%100) > 40)
                    {
                        c = cprev;
                    }
                    else
                    {
                        c = 'A' + rand()%('Z' - 'A');
                    }
                    buffer1[k] = c;
                    cprev = c;
                }
                //printf("DATA=%s\n", buffer1);
                /* Compress input buffer. */
                size2 = comp_exec(buffer1, size1, buffer2);
                /* Decompress compressed data. */
                size3 = decomp_exec(buffer2, size2, buffer3);

                printf("SIZE=%5d, COUNT=%5d, SZ1=%5d, SZ2=%5d, SZ3=%5d, CMP=%c\r", i, j, size1, size2, size3, (size2 >= size1 ? 'x' : 'o'));


                /* Compare original data and decompressed data. */
                int err=0;
                if(size3 == size1)
                {
                    for(k=0; k<size1; k++)
                    {
                        if(buffer1[k] != buffer3[k])
                        {
                            err = 1;
                            break;
                        }
                    }
                }
                else
                {
                    err = 1;
                }
                if(err == 1)
                {
                    printf("\n");
                    printf("ERROR ! SZ1=%d, SZ2=%d, SZ3=%d\n", size1, size2, size3);
                    FILE* fp;
                    fp = fopen("error1.bin", "wb");
                    if(fp)
                    {
                        fwrite(buffer1, 1, size1, fp);
                        fclose(fp); fp = NULL;
                    }
                    fp = fopen("error2.bin", "wb");
                    if(fp)
                    {
                        fwrite(buffer2, 1, size2, fp);
                        fclose(fp); fp = NULL;
                    }
                    fp = fopen("error3.bin", "wb");
                    if(fp)
                    {
                        fwrite(buffer3, 1, size3, fp);
                        fclose(fp); fp = NULL;
                    }


                    return 1;
                }
            }
        }
        printf("\n");
        printf("Test ended with success.\n");
    }

    return 0;
}



