/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "tools/skiaserve/Request.h"
#include "tools/skiaserve/Response.h"

#include "include/core/SkGraphics.h"
#include "tools/flags/CommandLineFlags.h"

#include "tools/skiaserve/urlhandlers/UrlHandler.h"

#include "microhttpd.h"

#include <errno.h>

#if !defined _WIN32
#include <sys/socket.h>
#include <arpa/inet.h>
#endif

using namespace skia_private;
using namespace Response;

static DEFINE_int(port, 8888, "The port to listen on.");
static DEFINE_string(address, "127.0.0.1", "The address to bind to.");
static DEFINE_bool(hosted, false, "Running in hosted mode on debugger.skia.org.");

class UrlManager {
public:
    UrlManager() {
        // Register handlers
        fHandlers.push_back(new RootHandler);
        fHandlers.push_back(new PostHandler);
        fHandlers.push_back(new ImgHandler);
        fHandlers.push_back(new ClipAlphaHandler);
        fHandlers.push_back(new EnableGPUHandler);
        fHandlers.push_back(new CmdHandler);
        fHandlers.push_back(new InfoHandler);
        fHandlers.push_back(new DownloadHandler);
        fHandlers.push_back(new DataHandler);
        fHandlers.push_back(new BreakHandler);
        fHandlers.push_back(new OpsHandler);
        fHandlers.push_back(new OpBoundsHandler);
        fHandlers.push_back(new ColorModeHandler);
        fHandlers.push_back(new QuitHandler);
    }

    ~UrlManager() {
        for (int i = 0; i < fHandlers.size(); i++) { delete fHandlers[i]; }
    }

    // This is clearly not efficient for a large number of urls and handlers
    int invoke(Request* request, MHD_Connection* connection, const char* url, const char* method,
               const char* upload_data, size_t* upload_data_size) const {
        for (int i = 0; i < fHandlers.size(); i++) {
            if (fHandlers[i]->canHandle(method, url)) {
                return fHandlers[i]->handle(request, connection, url, method, upload_data,
                                            upload_data_size);
            }
        }
        return MHD_NO;
    }

private:
    TArray<UrlHandler*> fHandlers;
};

const UrlManager kUrlManager;

int answer_to_connection(void* cls, struct MHD_Connection* connection,
                         const char* url, const char* method, const char* version,
                         const char* upload_data, size_t* upload_data_size,
                         void** con_cls) {
    SkDebugf("New %s request for %s using version %s\n", method, url, version);

    Request* request = reinterpret_cast<Request*>(cls);
    int result = kUrlManager.invoke(request, connection, url, method, upload_data,
                                    upload_data_size);
    if (MHD_NO == result) {
        fprintf(stderr, "Invalid method and / or url: %s %s\n", method, url);
    }
    return result;
}

int skiaserve_main() {
    SkGraphics::Init();
    Request request(SkString("/data")); // This simple server has one request

    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_port = htons(FLAGS_port);
    int result = inet_pton(AF_INET, FLAGS_address[0], &address.sin_addr);
    if (result != 1) {
        printf("inet_pton for %s:%d failed with return %d %s\n",
                FLAGS_address[0], FLAGS_port, result, strerror(errno));
        return 1;
    }

    printf("Visit http://%s:%d in your browser.\n", FLAGS_address[0], FLAGS_port);

    struct MHD_Daemon* daemon;
    daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY
#ifdef SK_DEBUG
                              | MHD_USE_DEBUG
#endif
                              , FLAGS_port, nullptr, nullptr,
                              &answer_to_connection, &request,
                              MHD_OPTION_SOCK_ADDR, &address,
                              MHD_OPTION_END);
    if (nullptr == daemon) {
        SkDebugf("Could not initialize daemon\n");
        return 1;
    }

    if (FLAGS_hosted) {
        while (1) {
            SkDebugf("loop\n");
            #if defined(SK_BUILD_FOR_WIN)
                Sleep(60 * 1000);
            #else
                sleep(60);
            #endif
        }
    } else {
        getchar();
    }
    MHD_stop_daemon(daemon);
    return 0;
}

#if !defined SK_BUILD_FOR_IOS
int main(int argc, char** argv) {
    CommandLineFlags::Parse(argc, argv);
    return skiaserve_main();
}
#endif
