/*
 * src/main.c
 * https://gitlab.com/bztsrc/assetpack
 *
 * Copyright (C) 2024 bzt, MIT license
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL ANY
 * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
 * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @brief Main source file for the apck utility
 */

#include "main.h"

#ifdef __WIN32__
#define SEP "\\"
#else
#define SEP "/"
#endif
int quiet = 0;

void usage(void)
{
    printf("Asset Pack - Copyright (C) 2024 bzt, MIT\n");
    printf("https://gitlab.com/bztsrc/assetpack\n\n");
    printf(" apck [-k <key>] [-e <engine>] [-v <version>] [-q] <input directory> <output.apck>\n");
    printf(" apck [-k <key>] <input.apck> <output directory>\n");
    printf(" apck [-k <key>] -d <input.apck>\n\n");
    printf("  -k <key>      specify AES-CBC-256 encryption key (32 hex digits)\n");
    printf("  -e <engine>   specify your engine's magic, up to 12 ASCII letters\n");
    printf("  -v <version>  specify your engine's version, in X.X.X format\n");
    printf("  -d            dump asset directory in archive\n");
    printf("  -h / -?       help, required directory structure\n");
    printf("  -q            quiet, surpress conversion errors\n");
    printf("\nIf the first argument is a directory, then it creates an archive.\n");
    printf("Otherwise if the first argument is an archive, then it unpacks.\n\n");
    exit(1);
}

void help(void)
{
    printf("Asset Pack - Copyright (C) 2024 bzt, MIT\n\nDirectory Structure:\n\n");
    printf("  icon.png          your application's icon\n");
    printf("  locales"SEP"xx_XX.po  translated texts (gettext PO)\n");
    printf("  locales"SEP"xx_XX"SEP"*   localized voices, images with texts\n");
    printf("  images"SEP"*          plain images (PNG, JPG, WEBP, GIF, BMP)\n");
    printf("  sprites"SEP"*         animation frames (PNG, JPG, WEBP, GIF, BMP)\n");
    printf("  bgm"SEP"*             background music (WAV, MP3, OGG)\n");
    printf("  sfx"SEP"*             sound effects (WAV, MP3, OGG)\n");
    printf("  fonts"SEP"*           fonts (OTF, TTF, WOFF, PS, SFD, BMF, BDF, SFN, ...)\n");
    printf("  videos"SEP"*          videoclips (OGV Theora)\n");
    printf("  models"SEP"*          3D models (M3D)\n");
    printf("  maps"SEP"*            maps (Tiled TMX)\n");
    printf("  objects"SEP"*         any arbitrary format\n");
    printf("  scripts"SEP"*         any arbitrary format\n");
    printf("\n");
    exit(0);
}

int main(int argc, char **argv)
{
    uint64_t size;
    void *f;
    char *input = NULL, *output = NULL, *engine = NULL, *s;
    uint32_t version = 0;
    int encrypt = 0, dump = 0, i, m;

    /* parse command line arguments and load input files */
    if(argc < 2) usage();

    for(i = 1; i < argc; i++) {
        if(argv[i][0] == '-')
            switch(argv[i][1]) {
                case 'h': case '?': help(); break;
                case 'q': quiet++; break;
                case 'e': engine = argv[++i]; break;
                case 'v':
                    for(version = 0, s = argv[++i], m = 24; *s && m >= 0; m -= 8) {
                        if(*s == '.') s++;
                        version |= atoi(s) << m;
                        while(*s && (*s >= '0' && *s <= '9')) s++;
                    }
                break;
                case 'k':
                    s = argv[++i];
                    if(!s || strlen(s) != 32) {
                        fprintf(stderr, "bad key length, must be 32 hex digits (this is %d)\n", (int)strlen(s));
                        return 1;
                    }
                    for(m = 0; *s && m < 16; m++) {
                        aes_ivkey[m] = (*s >= '0' && *s <= '9' ? *s - '0' : (*s >= 'a' && *s <= 'f' ? *s - 'a' + 10 :
                            (*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : 0))) << 4;
                        s++;
                        aes_ivkey[m] |= (*s >= '0' && *s <= '9' ? *s - '0' : (*s >= 'a' && *s <= 'f' ? *s - 'a' + 10 :
                            (*s >= 'A' && *s <= 'F' ? *s - 'A' + 10 : 0)));
                        s++;
                    }
                    encrypt = 1;
                break;
                case 'd': dump++; break;
            }
        else
        if(!input) input = argv[i]; else
        if(!output) output = argv[i];
    }
    if(!input || (!dump && !output))
        usage();

    if((f = apck_fileopen(input, &size))) {
        /* if input is a file, we unpack */
        apck_fileclose(f);
        unpack(input, output);
    } else {
        /* otherwise pack. Open the output for writing */
        if(!(f = apck_fileopenw(output))) {
            fprintf(stderr, "unable to write '%s'\n", output);
            return 1;
        }
        /* pack directory contents */
        pack(input, f, engine, version, encrypt, 2048);
        /* close the file */
        apck_fileclose(f);
    }
    return 0;
}
