#include "AndroidAssetManager.h"
#include "Log.h"
#include "NativeEngine.h"
#include <iostream>
#include <fstream>

#include <game-activity/native_app_glue/android_native_app_glue.h>

AndroidAssetManager::AndroidAssetManager() : AssetManager(), m_asset_mgr(nullptr){};
AndroidAssetManager::~AndroidAssetManager() {}

void AndroidAssetManager::create(AAssetManager* android_asset_manager)
{
    AndroidAssetManager* m = new AndroidAssetManager;
    m->m_asset_mgr = android_asset_manager;
    AssetManager::ptr = m;
}

bool AndroidAssetManager::loadFile(const char* path, FileBuffer* p_file_buffer)
{
    AAsset* asset = AAssetManager_open(m_asset_mgr, path, AASSET_MODE_BUFFER);
    if (!asset) {
        ALOGE("Failed to open asset %s", path);
        return false;
    }
    const void* buffer = AAsset_getBuffer(asset);
    if (!buffer) {
        ALOGE("Failed to retrieve contents of asset %s", path);
        return false;
    }
    auto length = static_cast<size_t>(AAsset_getLength64(asset));
    p_file_buffer->data = buffer;
    p_file_buffer->size = length;
    p_file_buffer->internal = asset;
    return true;
}

void AndroidAssetManager::releaseFileBuffer(FileBuffer& fb)
{
    if (fb.internal != nullptr){
        AAsset_close(reinterpret_cast<AAsset*>(fb.internal));
    }
    fb.internal = nullptr;
    fb.data = nullptr;
    fb.size = 0;
}

bool AndroidAssetManager::writeFile(const char* path, const void* data, size_t size)
{
    std::string pfad_komplett = "data/data/tech.recreational.kde/" + std::string(path);
    std::ofstream file;
    file.open(pfad_komplett, std::fstream::in | std::fstream::out | std::fstream::trunc);
    if (file.is_open()) {
        //file << data;
        if (!file.good()){
            return false;
        }
        if (file.bad()){
            return false;
        }
        if (file.fail()){
            return false;
        }
        if (file.eof()){
            return false;
        }
        file.clear();
        file.write((const char*)data, size);
        auto flags = file.flags();
        if (!file.good()){
            return false;
        }
        if (file.bad()){
            return false;
        }
        if (file.fail()){
            return false;
        }
        if (file.eof()){
            return false;
        }
        std::streamsize size = file.width();
        file.close();
        std::cout << "Datei erfolgreich erstellt und beschrieben." << std::endl;
    } else {
        std::cout << "Fehler beim Erstellen der Datei." << std::endl;
    }
    return true;
}

size_t AndroidAssetManager::getInternFileSize(const char* path){
    std::string dir = "data/data/tech.recreational.kde/" + std::string(path);
    std::ifstream myfile(dir);
    std::string line;
    size_t size = 0;
    if (myfile.is_open()) {
        while (std::getline(myfile, line)) {
            size += line.size();
        }
        myfile.close();
    }
    return size;
}

bool AndroidAssetManager::loadInternFile(const char* path, FileBuffer* p_file_buffer)
{
    p_file_buffer->internal = nullptr;
    p_file_buffer->data = nullptr;
    p_file_buffer->size = 0;
    size_t size = getInternFileSize(path);
    if (size == 0){
        return false;
    }
    std::string dir = "data/data/tech.recreational.kde/" + std::string(path);
    std::ifstream myfile(dir);
    //std::string line;
    if (myfile.is_open())
    {
        p_file_buffer->size = size;
        char* data = (char*)malloc(size + 1);
        if (data == nullptr){
            myfile.clear();
            myfile.close();
            return false;
        }
        //myfile.get(data, size);
        std::string line;
        int pos = 0;
        while (std::getline(myfile, line)) {
            size_t line_size = line.size();
            const char* line_text = line.c_str();
            memcpy(&data[pos], line_text, line_size);
            pos += line_size;
        }
        data[pos] = '\0';
        p_file_buffer->data = data;
        myfile.clear();
        myfile.close();
        return true;
    }
    return false;
}