/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2026 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>

#include "demo_table.h"

#ifndef UI_WIN32

int main(int argc, char **argv) {
#ifdef UI_GTK4
    ui_init(NULL, argc, argv);
    ui_onstartup(application_startup, NULL);
    ui_main();
#else
    printf("not supported yet\n");
#endif
    return 0;
}

#else

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    //ui_init(NULL, argc, argv);
    //ui_onstartup(application_startup, NULL);
    //ui_main();
    return 0;
}

#endif

static void init_toolbar(void) {
    
}

static void create_main_window(void) {
    UiObject *obj = ui_window("Table Demo");
    
    MainWindow *wdata = ui_zalloc(obj->ctx, sizeof(MainWindow));
    wdata->model = ui_model_new(obj->ctx, NULL);
    wdata->data = ui_list_new(obj->ctx, NULL);
    wdata->indices = ui_list_new(obj->ctx, NULL);
    wdata->columnname = ui_string_new(obj->ctx, NULL);
    
    obj->window = wdata;
    
    ui_table(obj, .fill = TRUE, .list = wdata->data, .model = wdata->model,
            .getvalue2 = row_get_data, .onsave = row_save);
    
    ui_grid(obj, .margin = 10, .columnspacing = 6, .rowspacing = 6, .def_vfill = TRUE) {
        ui_rlabel(obj, .label = "Index");
        ui_dropdown(obj, .list = wdata->indices);
        ui_rlabel(obj, .label = "Name");
        ui_textfield(obj, .value = wdata->columnname, .hfill = TRUE, .hexpand = TRUE);
        ui_button(obj, .label = "Add", .onclick = add_column);
        ui_button(obj, .label = "Remove", .onclick = remove_column);
        
        ui_newline(obj);
        ui_button(obj, .colspan = 6, .label = "Add Row", .onclick = add_row);
    }
    
    update_indices(wdata);
    
    ui_show(obj);
}

void application_startup(UiEvent *event, void *userdata) {
    init_toolbar();
    create_main_window();
}

void update_indices(MainWindow *wdata) {
    UiList *list = wdata->indices;
    
    // clear previous values
    char *elm = list->first(list);
    while(elm) {
        free(elm);
        elm = list->next(list);
    }
    ui_list_clear(wdata->indices);
    
    char buf[32];
    for(int i=0;i<=wdata->model->columns;i++) {
        snprintf(buf, 32, "%d", i);
        ui_list_append(list, strdup(buf));
    }
    
    ui_list_update(wdata->indices);
}

void add_column(UiEvent *event, void *userdata) {
    MainWindow *wdata = event->window;
    
    char *name = ui_get(wdata->columnname);
    size_t namelen = strlen(name);
    
    if(namelen == 0) {
        printf("cannot add column: no name specified\n");
        return;
    }
    
    int index = ui_list_getselection(wdata->indices);
    
    ui_model_insert_column(wdata->model, index, UI_STRING_EDITABLE, NULL, name, 0, TRUE);
    ui_set(wdata->columnname, "");
    
    update_indices(wdata);
    
    ui_list_setselection(wdata->indices, wdata->model->columns);
}

void remove_column(UiEvent *event, void *userdata) {
    MainWindow *wdata = event->window;
    int index = ui_list_getselection(wdata->indices);
    
    if(index < 0 || index >= wdata->model->columns) {
        printf("cannot remove column: invalid index: %d\n", index);
        return;
    }
    
    ui_model_remove_column(wdata->model, index);
    update_indices(wdata);
    ui_list_setselection(wdata->indices, wdata->model->columns);
}

void add_row(UiEvent *event, void *userdata) {
    MainWindow *wdata = event->window;
    
    TableRow *row = malloc(sizeof(TableRow));
    memset(row, 0, sizeof(TableRow));
    
    ui_list_append(wdata->data, row);
    ui_list_update(wdata->data);
    
    print_table_data(wdata);
}

void* row_get_data(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
    TableRow *row_data = elm;
    return row_get(row_data, col);
}

UiBool row_save(UiList *list, void *elm, int row, int col, UiCellValue *value, void *userdata) {
     if(value->type != UI_STRING_EDITABLE) {
         return FALSE;
     }
     TableRow *row_data = elm;
     row_set(row_data, col, value->string);
     
     return TRUE;
}

void row_set(TableRow *row, int index, const char *value) {
    if(index >= row->capacity) {
        size_t old_capacity = row->capacity;
        row->capacity += 8;
        char **columns = calloc(row->capacity, sizeof(char*));
        if(row->columns) {
            memcpy(columns, row->columns, old_capacity * sizeof(char*));
            free(row->columns);
        }
        row->columns = columns;
    }
    free(row->columns[index]);
    row->columns[index] = strdup(value);
}

char* row_get(TableRow *row, int index) {
    if(index >= row->capacity) {
        return NULL;
    }
    return row->columns[index];
}


void print_table_data(MainWindow *wdata) {
    printf("table data:\n-----------------\n\n");
    UiList *list = wdata->data;
    TableRow *elm = list->first(list);
    while(elm) {
        for(int i=0;i<elm->capacity;i++) {
            printf("[%d]: %s\n", i, elm->columns[i]);
        }
        printf("\n");
        
        elm = list->next(list);
    }
    printf("\n\n");
}
