/*
 * Copyright 2009, The Android Open Source Project
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */


#include <iostream>
#include <string>
#include <vector>

static const char gSite[] = "http://www.corp.google.com/eng/doc/emoji/dev.html";

using namespace std;

static int hexchar_to_int(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    }
    if (c >= 'A' && c <= 'F') {
        return 10 + c - 'A';
    }
    if (c >= 'a' && c <= 'f') {
        return 10 + c - 'a';
    }
    return -1;  // unrecognized char for nex
}

/*  Tool to build gmoji_pua table, listing all of the pua values for gmoji
 */
int main (int argc, char * const argv[]) {
    
    char buffer[10000];    
    FILE* file = fopen(argv[1], "r");
    if (NULL == file) {
        std::cerr << "Can't open " << argv[1] << " for input. Aborting\n";
        std::cout << "\n";
        return -1;
    }
    
    vector<int> unichars;
    int lineNo = 0;
    for (;;) {
        if (fgets(buffer, sizeof(buffer), file) == 0) {
            break;
        }
        
        int prevPua = 0;
        int pua = 0;
        // we just want to eat the first 5 chars
        for (int i = 0; i < 5; i++) {
            int value = hexchar_to_int(buffer[i]);
            if (value < 0) {    // bad char for hex
                std::cerr << "Expected hex char on line " << lineNo
                          << " col " << i << "\n";
                return -1;
            }
            pua = (pua << 4) | value;
        }
        if (pua < 0xFE000 || pua > 0xFEFFF) {
            std::cerr << "PUA not in expected range " << pua << " line "
                      << lineNo << "\n";
            return -1;
        }
        if (pua <= prevPua) {
            std::cerr << "PUA value not in ascending order line "
                      << lineNo << "\n";
            return -1;
        }
        unichars.push_back(pua);
        prevPua = pua;
        lineNo++;
    }
    
    // Now output our resulting array to look like a C array
    const int perLine = 8;
    const int base = unichars[0];
    printf("\n");
    printf("// Compressed gmoji table, sorted\n");
    printf("// Originally scraped from %s\n", gSite);
    printf("// Input text file \"%s\"\n", argv[1]);
    printf("\n");
    printf("static const uint16_t gGmojiPUA[] = {\n");
    for (int i = 0; i < unichars.size(); i++) {
        if ((i % perLine) == 0) {   // first one
            printf("    ");
        }
        printf("0x%03X", unichars[i] - base);
        if (i == unichars.size() - 1) { // last one entirely
            printf("\n");
        }
        else if ((i % perLine) == (perLine - 1)) {   // last one on line
            printf(",\n");
        } else {
            printf(", ");
        }
    }
    printf("};\n");
    printf("\n");
    printf("#define GMOJI_PUA_MIN   0x%X\n", unichars[0]);
    printf("#define GMOJI_PUA_MAX   0x%X\n", unichars[unichars.size()-1]);
    printf("#define GMOJI_PUA_COUNT (sizeof(gGmojiPUA) / sizeof(gGmojiPUA[0]))\n");
    printf("// GMOJI_PUA_COUNT should be %d\n", unichars.size());
    printf("\n");
    
    fclose(file);
    return 0;
}