// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html

#include <iostream>
#include <tinyutf8/tinyutf8.h>
#include <fstream>
#include <vector>
#include "assert.hpp"
#include "../lib/javacompat.hpp"


int main(){

    // metadata for things in resources/unicode_data/
    // normal_utf-8: 116 bytes, 85 characters ??
    // java-style_unicode: 119 bytes, 85 characters ??

    std::cout << "################################################################################" << std::endl;
    std::cout << "Javacompat tests" << std::endl;
    std::cout << "################################################################################" << std::endl;

    char* nextChar = new char;

    std::streampos javaSize;
    std::string javaStdString;
    const char* javaFilePath = "./resources/unicode_data/java-style_unicode";
    std::ifstream javaFile(javaFilePath, std::ios::in | std::ios::binary | std::ios::ate);
    if(javaFile.is_open()){
        javaSize = javaFile.tellg();
        javaFile.seekg(0, std::ios::beg);

        for (int i=0; i<javaSize; i++) {
            javaFile.read(nextChar, 1);
            javaStdString.push_back(*nextChar);
        }

        javaFile.close();
    } else {
        std::cerr << "Failed to open file: " << javaFilePath << std::endl;
        return 2;
    }

    tiny_utf8::string importedString = JavaCompat::importJavaString(reinterpret_cast<uint8_t*>(javaStdString.data()), 0x75).value;

    std::streampos normalSize;
    std::string normalStdString;
    const char* normalFilePath = "./resources/unicode_data/normal_utf-8";
    std::ifstream normalFile(normalFilePath, std::ios::in | std::ios::binary | std::ios::ate);
    if(normalFile.is_open()){
        normalSize = normalFile.tellg();
        normalFile.seekg(0, std::ios::beg);

        for (int i=0; i<normalSize; i++) {
            normalFile.read(nextChar, 1);
            normalStdString.push_back(*nextChar);
        }

        normalFile.close();
    } else {
        std::cerr << "Failed to open file: " << normalFilePath << std::endl;
        return 2;
    }

    tiny_utf8::string normalString = tiny_utf8::string(normalStdString);

    // check for normal operation
    ASSERT(normalString == importedString);

    // check for mismatched size error
    std::string javaStdStringCopy = javaStdString;
    javaStdStringCopy[0]='b';
    ErrorOr<tiny_utf8::string> errorString = JavaCompat::importJavaString(reinterpret_cast<uint8_t*>(javaStdStringCopy.data()), 0x75);
    ASSERT(errorString.isError);
    ASSERT(errorString.errorCode == ErrorCodes::MISMATCHEDSIZE);

    std::cout << "Passed Import Java string test." << std::endl;

    //using normalString from when we read the file earlier
    //there's no need to read the same file twice

    std::vector<uint8_t> data = JavaCompat::exportJavaString(normalString).value;
    std::string exportedString = std::string();
    for(int i=0; i<(int) data.size(); i++){
        exportedString.push_back(data[i]);
    }

    ASSERT(exportedString == javaStdString);
    std::cout << "Passed Export Java string test." << std::endl;
    delete nextChar;

    return 0;
}
