/*
    * actions.cpp
    * Clipboard, rename, delete, and context-menu actions for the embedded desktop file manager
    * Copyright (c) 2026 Daniel Hammer
*/

#include "filemanager_internal.hpp"

namespace filemanager {

static void filemanager_load_clipboard(FileManagerState* fm, bool is_cut) {
    if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
    if (fm->entry_count <= 0) return;

    int* sel = (int*)montauk::malloc((uint64_t)fm->entry_count * sizeof(int));
    if (!sel) return;
    int n = filemanager_collect_selection(fm, sel, fm->entry_count);
    if (n <= 0) { montauk::mfree(sel); return; }
    if (!filemanager_ensure_clipboard_capacity(fm, n)) { montauk::mfree(sel); return; }

    int out = 0;
    for (int i = 0; i < n && out < fm->clipboard_cap; i++) {
        int idx = sel[i];
        if (fm->entry_types[idx] == FM_ENTRY_DRIVE) continue;
        filemanager_build_fullpath(fm->clipboard_paths[out], 256,
                                   fm->current_path, fm->entry_names[idx]);
        out++;
    }
    montauk::mfree(sel);
    if (out == 0) return;

    fm->clipboard_count = out;
    fm->clipboard_is_cut = is_cut;
}

void filemanager_do_copy(FileManagerState* fm) {
    filemanager_load_clipboard(fm, false);
}

void filemanager_do_cut(FileManagerState* fm) {
    filemanager_load_clipboard(fm, true);
}

void filemanager_do_paste(FileManagerState* fm) {
    // Copy/move runs on a worker thread with a progress dialog (a small single
    // file pastes inline). Same-volume moves use rename (instant, no copy).
    filemanager_start_paste_job(fm);
}

void filemanager_start_rename(FileManagerState* fm) {
    if (fm->selected < 0 || fm->selected >= fm->entry_count) return;
    if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm) ||
        fm->entry_types[fm->selected] == FM_ENTRY_DRIVE) return;

    fm->rename_active = true;
    fm->rename_idx = fm->selected;
    montauk::strcpy(fm->rename_buf, fm->entry_names[fm->selected]);
    fm->rename_len = montauk::slen(fm->rename_buf);
    fm->rename_cursor = fm->rename_len;
}

void filemanager_finish_rename(FileManagerState* fm) {
    if (!fm->rename_active) return;
    fm->rename_active = false;

    // If name unchanged, skip
    if (montauk::streq(fm->rename_buf, fm->entry_names[fm->rename_idx])) return;
    if (fm->rename_len == 0) return;

    char old_path[512], new_path[512];
    filemanager_build_fullpath(old_path, 512,
                               fm->current_path, fm->entry_names[fm->rename_idx]);
    filemanager_build_fullpath(new_path, 512,
                               fm->current_path, fm->rename_buf);

    if (montauk::frename(old_path, new_path) != 0) {
        // Fall back to copy + delete for drivers that don't support rename
        if (fm->is_dir[fm->rename_idx]) {
            if (filemanager_copy_dir_recursive(old_path, new_path))
                filemanager_delete_recursive(old_path);
        } else {
            if (filemanager_copy_file(old_path, new_path))
                montauk::fdelete(old_path);
        }
    }

    filemanager_read_dir(fm);
}

void filemanager_cancel_rename(FileManagerState* fm) {
    fm->rename_active = false;
}

void filemanager_new_folder(FileManagerState* fm) {
    if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;

    // Find a unique name
    char name[64] = "New Folder";
    char path[512];
    filemanager_build_fullpath(path, 512, fm->current_path, name);
    int attempt = 1;
    // Try creating; if it fails, append a number
    if (montauk::fmkdir(path) != 0) {
        for (attempt = 2; attempt <= 99; attempt++) {
            snprintf(name, 64, "New Folder %d", attempt);
            filemanager_build_fullpath(path, 512, fm->current_path, name);
            if (montauk::fmkdir(path) == 0) break;
        }
    }

    filemanager_read_dir(fm);

    // Select the new folder and start rename
    for (int i = 0; i < fm->entry_count; i++) {
        if (montauk::streq(fm->entry_names[i], name)) {
            fm->selected = i;
            filemanager_start_rename(fm);
            break;
        }
    }
}

void filemanager_delete_selected(FileManagerState* fm) {
    if (filemanager_is_computer_view(fm) || filemanager_is_virtual_view(fm)) return;
    if (fm->entry_count <= 0) return;

    int* sel = (int*)montauk::malloc((uint64_t)fm->entry_count * sizeof(int));
    if (!sel) return;
    int n = filemanager_collect_selection(fm, sel, fm->entry_count);
    if (n <= 0) { montauk::mfree(sel); return; }

    // Filter out drives.
    int* filtered = (int*)montauk::malloc((uint64_t)n * sizeof(int));
    if (!filtered) { montauk::mfree(sel); return; }
    int fn = 0;
    bool any_dir = false;
    for (int i = 0; i < n; i++) {
        int idx = sel[i];
        if (fm->entry_types[idx] == FM_ENTRY_DRIVE) continue;
        filtered[fn++] = idx;
        if (fm->is_dir[idx]) any_dir = true;
    }
    montauk::mfree(sel);
    if (fn == 0) { montauk::mfree(filtered); return; }

    // Anything with a directory or multi-item selection: confirm first.
    if (any_dir || fn > 1) {
        if (fn == 1 && any_dir) {
            filemanager_show_directory_delete_confirmation(fm, filtered[0]);
        } else {
            filemanager_show_bulk_delete_confirmation(fm, filtered, fn);
        }
        montauk::mfree(filtered);
        return;
    }

    // Single plain file: delete immediately.
    char fullpath[512];
    filemanager_build_fullpath(fullpath, 512,
                               fm->current_path, fm->entry_names[filtered[0]]);
    montauk::mfree(filtered);
    montauk::fdelete(fullpath);
    filemanager_clear_multi_selection(fm);
    filemanager_read_dir(fm);
}

void filemanager_open_ctx_menu(FileManagerState* fm, int local_x, int local_y, int target_idx) {
    fm->ctx_open = true;
    fm->ctx_x = local_x;
    fm->ctx_y = local_y;
    fm->ctx_target_idx = target_idx;
    fm->ctx_hover = -1;
    fm->ctx_item_count = 0;

    if (target_idx >= 0 && target_idx < fm->entry_count) {
        int tt = fm->entry_types[target_idx];
        if ((filemanager_is_computer_view(fm)
             && (tt == FM_ENTRY_DRIVE || tt == FM_ENTRY_HOME || tt == FM_ENTRY_APPS_ROOT
                 || tt == FM_ENTRY_SPECIAL_DIR || tt == FM_ENTRY_SYSTEM_CONFIGURATION_ROOT))
            || (filemanager_is_virtual_view(fm) && tt == FM_ENTRY_VIRTUAL_APP)) {
            // Drive, Home, Apps shortcut, or app entry: only Open
            fm->ctx_items[fm->ctx_item_count++] = CTX_OPEN;
            fm->ctx_items[fm->ctx_item_count++] = CTX_PROPERTIES;
        } else {
            fm->ctx_items[fm->ctx_item_count++] = CTX_OPEN;
            fm->ctx_items[fm->ctx_item_count++] = CTX_COPY;
            fm->ctx_items[fm->ctx_item_count++] = CTX_CUT;
            fm->ctx_items[fm->ctx_item_count++] = CTX_RENAME;
            fm->ctx_items[fm->ctx_item_count++] = CTX_DELETE;
            fm->ctx_items[fm->ctx_item_count++] = CTX_PROPERTIES;
        }
    } else {
        // Background click
        if (filemanager_is_virtual_view(fm)) {
            fm->ctx_open = false;
            return;
        }
        if (filemanager_is_computer_view(fm)) {
            fm->ctx_items[fm->ctx_item_count++] = CTX_REFRESH;
        } else {
            if (fm->clipboard_count > 0)
                fm->ctx_items[fm->ctx_item_count++] = CTX_PASTE;
            fm->ctx_items[fm->ctx_item_count++] = CTX_NEW_FOLDER;
        }
    }
}

void filemanager_close_ctx_menu(FileManagerState* fm) {
    fm->ctx_open = false;
    fm->ctx_hover = -1;
}

} // namespace filemanager
