#include <gtk/gtk.h>

#include <validate.h>
#include <paint.h>

#define DATA_KILL_APP 1

extern GtkApplication *app;
int dont_kill_the_app_pls = 0;

/**
 * This function is deliberately simple to make it easier to debug for the 
 * contestants
 */
int check_is_key_valid(const char* key)
{
    int ret = 0;

    /* Duplicate the key so we can edit it */
    char* dup = strdup(key);

    if (strlen(dup) != KEYLENGTH) goto cleanup;

    /* Not the correct format */
    if (dup[4] != '-' || dup[9] != '-' || dup[14] != '-') goto cleanup;

    dup[4] = '\0';
    dup[9] = '\0';
    dup[14] = '\0';
    
    /* Starts with SHTP */
    if (strcmp(dup, "SHTP")) goto cleanup;

    int a = strtol(&dup[5], NULL, 16);
    int b = strtol(&dup[10], NULL, 16);
    int c = strtol(&dup[15], NULL, 16);

    /* these are too simple, they are not allowed */
    if (a < 256 || b < 256) goto cleanup;

    if ((a ^ b) != c) goto cleanup;
    
    ret = 1;

cleanup:
    free(dup);
    return ret;
}

static void invalid_key(GtkWindow* window)
{
    GtkWidget* dialog = gtk_message_dialog_new(window, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Your entered key is not valid");

    g_signal_connect_swapped(GTK_WINDOW(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog);
    
    gtk_widget_show_all(dialog);
    gtk_widget_show_all(GTK_WIDGET(window));
}

static void save_key(const char* key)
{
    FILE* f = fopen(KEYSTORE_FILE, "w+");
    fprintf(f, key);
    fclose(f);
}

G_MODULE_EXPORT void button_validate_clicked(GtkWidget* widget, gpointer data)
{
    GtkWidget* window = gtk_widget_get_toplevel(widget);
    GtkEntryBuffer* buffer = gtk_entry_get_buffer(GTK_ENTRY(data));
    const char* key = gtk_entry_buffer_get_text(buffer);

    if (!check_is_key_valid(key))
    {
        invalid_key(GTK_WINDOW(window));
        return;
    }

    /* The key was valid, save the key for later and start the program */
    save_key(key);

    /* Destroy the old window, but make sure the application doesn't exit by overriding the destroy event */
    dont_kill_the_app_pls = 1;
    gtk_window_close(GTK_WINDOW(window));

    /* start the actual paint app */
    build_paint();
}

static void close_application(GtkWidget* widget, gpointer data)
{
    /* Ugly, hacky, but it works */
    if (!dont_kill_the_app_pls)
        g_application_quit(G_APPLICATION(app));
}

extern const char* validate_xml;

void build_license_key_popup()
{
    GtkBuilder* builder = gtk_builder_new_from_string(validate_xml, strlen(validate_xml));
    gtk_builder_set_application(builder, app);
    gtk_builder_connect_signals(builder, NULL);
    GtkWidget* window = GTK_WIDGET(gtk_builder_get_object(builder, "validate_window"));
    g_signal_connect(window, "destroy", G_CALLBACK(close_application), NULL);
    gtk_widget_show_all(window);
}