#include <File.h>
#include <FileSystem.h>
#include <Font.h>
#include <GraphicsApi.h>
#include <HttpRequest.h>
#include <JSON.h>
#include <main.h>
#include <Network.h>
#include <RenderThread.h>
#include <Screen.h>
#include <Texture.h>
#include <Window.h>

#include "CustomDX11API.h"
#include "Globals.h"
#include "Initialization.h"

void createModels(Screen* zScreen);

/* Test rendering of specific block types
int KSGStart Framework::Start(Framework::Startparam p)
{
    Network::Start(20);
    initVariables();
    setDebugDX(1);

    File d;
    d.setFile("data/schriften");
    auto list = d.getFileList();
    for (Text* fontFile : *list)
    {
        LTDSFile dat;
        dat.setPfad(
            new Text(Text("data/schriften/").operator+(fontFile->getText())));
        dat.readData();
        Text* name = fontFile->getTeilText(0, fontFile->getLength() - 5);
        fontRegister->put(*name, RCPointer<Font>::of(dat.loadFont()));
        name->release();
    }
    list->release();

    NativeWindow window;
    ::window = &window;
    WNDCLASS wc = Framework::F_Normal(p.hinst);
    wc.lpszClassName = "Factory Craft";
    window.create(WS_POPUPWINDOW, wc);
    Monitor m = Framework::getMonitor(0);
    window.setBounds(Point(m.x, m.y), Point(m.width, m.height));
    window.setDisplayMode(SW_SHOWNORMAL);
    window.setPreCloseAction([&window](void* p, void* f) {
        StopMessageLoop(window.getWindowHandle());
    });
    window.setMouseAction(_ret1ME);
    window.setKeyboardAction(_ret1TE);
    Screen3D screen(
        dynamic_cast<NativeWindow*>(window.getThis()), new CustomDX11API());
    screen.setHandleUserInputsOnTick(1);
    window.setScreen(dynamic_cast<Screen*>(screen.getThis()));
    screen.setFillColor(0);

    uiFactory = Framework::defaultUI(fontRegister->get("normal"), &screen);

    createModels(&screen);

    // loading textures
    File texturF;
    texturF.setFile("data/textures");
    RCArray<Text>* files = texturF.getFileList();
    if (files)
    {
        int count = 0;
        for (Text* fileName : *files)
        {
            LTDBFile dat;
            dat.setFile(new Text(Text("data/textures/") + *fileName));
            dat.readData(0);
            count += dat.getImageCount();
        }
        for (Text* fileName : *files)
        {
            LTDBFile dat;
            dat.setFile(new Text(Text("data/textures/") + *fileName));
            dat.readData(0);
            for (Text* name : *dat.zImageListe())
            {
                Image* b = dat.load(0, new Text(*name));
                screen.zGraphicsApi()
                    ->createOrGetTexture(*fileName + "/" + *name, b)
                    ->release();
            }
        }
        files->release();
    }

    BlockType* type = new BlockType(
        26, 1, ModelInfo("cube", "fluids.ltdb/water.png", 0, 6), 10, 1); //
block type to render Block* b = type->createBlock(Vec3<float>(0, 0, 0));
    unsigned char light[] = {255, 255, 255, 255, 255, 255};
    b->setLightData(TOP, light);
    b->setLightData(NORTH, light);
    b->setLightData(EAST, light);
    b->setLightData(SOUTH, light);
    b->setLightData(WEST, light);
    b->setLightData(BOTTOM, light);
    Chunk *c = new Chunk(Point(0, 0));
    c->setBlock(b);
    World3D* w = new World3D();
    w->addCollection(c);
    Cam3D* kam = new Cam3D();
    kam->setStyle(
        Cam3D::Style::Movable | Cam3D::Style::Rotatable | Cam3D::Style::Tick);
    kam->setPosition(Vec3<float>(10, 0, 0));
    kam->setAusrichtung(Vec3<float>(0, 0, 0));
    kam->setWorld(w);
    screen.addKamera(kam);

    RenderTh rTh;
    rTh.setMaxFps(60);
    rTh.setQuiet(1);
    rTh.setScreen(dynamic_cast<Screen*>(screen.getThis()));

    rTh.beginn();
    StartMessageLoop();
    rTh.terminate();
    releaseVariables();
    Network::Exit();
    return 0;
}
*/

RenderTh* renderThread;

int KSGStart Framework::Start(Framework::Startparam p)
{
    Network::Start(20);
    initVariables();
    setDebugDX(1);
#ifdef _DEBUG
    Logging::LoggingChannel* outputDebugLoggingChannel
        = new Framework::Logging::OutputDebugStringLoggingChannel();
    Framework::Logging::zLoggingHandler()->addChannel(
        Logging::LogLevel::Error, outputDebugLoggingChannel);
    Framework::Logging::zLoggingHandler()->addChannel(Logging::LogLevel::Debug,
        dynamic_cast<Logging::LoggingChannel*>(
            outputDebugLoggingChannel->getThis()));
    Framework::Logging::zLoggingHandler()->addChannel(Logging::LogLevel::Info,
        dynamic_cast<Logging::LoggingChannel*>(
            outputDebugLoggingChannel->getThis()));
    Framework::Logging::zLoggingHandler()->addChannel(
        Logging::LogLevel::Warning,
        dynamic_cast<Logging::LoggingChannel*>(
            outputDebugLoggingChannel->getThis()));
    Framework::Logging::zLoggingHandler()->addChannel(Logging::LogLevel::Trace,
        dynamic_cast<Logging::LoggingChannel*>(
            outputDebugLoggingChannel->getThis()));
#endif
    File d;
    d.setFile("data/schriften");
    auto list = d.getFileList();
    for (Text* fontFile : *list)
    {
        LTDSFile dat;
        dat.setPfad(
            new Text(Text("data/schriften/").operator+(fontFile->getText())));
        dat.readData();
        Text* name = fontFile->getTeilText(0, fontFile->getLength() - 5);
        fontRegister->put(*name, RCPointer<Font>::of(dat.loadFont()));
        name->release();
    }
    list->release();

    NativeWindow window;
    ::window = &window;
    WNDCLASS wc = Framework::F_Normal(p.hinst);
    wc.lpszClassName = "Factory Craft";
    window.create(WS_POPUPWINDOW, wc);
    Monitor m = Framework::getMonitor(0);
    window.setBounds(Point(m.x, m.y), Point(m.width, m.height));
    window.setDisplayMode(SW_SHOWNORMAL);
    window.setPreCloseAction([&window](void* p, void* f) {
        StopMessageLoop(window.getWindowHandle());
    });
    window.setMouseAction(_ret1ME);
    window.setKeyboardAction(_ret1TE);
    Screen3D screen(
        dynamic_cast<NativeWindow*>(window.getThis()), new CustomDX11API());
    screen.setHandleUserInputsOnTick(0);
    window.setScreen(dynamic_cast<Screen*>(screen.getThis()));
    screen.setFillColor(0);
    screen.setTestRend(0);

    uiFactory = Framework::defaultUI(fontRegister->get("normal"), &screen);
    uiFactory.createButton = createButton;
    uiFactory.createTextField = createTextField;
    uiFactory.createCheckBox = createCheckBox;
    uiFactory.createObjTable = createObjTable;
    uiFactory.createWindow = createWindow;
    initMenus();

    RenderTh rTh;
    rTh.setMaxFps(-1);
    rTh.setQuiet(0);
    rTh.setScreen(dynamic_cast<Screen*>(screen.getThis()));
    rTh.setTickFunktion([](void* p, void* o, double time) {
        if (World::INSTANCE)
        {
            World::INSTANCE->onTick(time);
        }
    });
    renderThread = &rTh;

    rTh.beginn();
    StartMessageLoop();
    rTh.terminate();

    releaseVariables();
    Network::Exit();
    return 0;
}