# Filter Module data flow

## What It Does
Filter subsystem enables Excel-like filtering for ranges: it computes predicates, builds filter UI (popup, checkbox tree, custom dialogs), applies predicates to sheet data (via DataManager/getData), and hides/unhides rows. It supports virtualized sheets, frozen panes, context-menu sorting/filtering hooks, and integrates with the workbook action pipeline.

Primary implementation files: `src/spreadsheet/integrations/filter.ts` (UI) and `src/workbook/integrations/filter.ts` (Core).

## Entry Points (UI)
**Class:** `Filter` (`src/spreadsheet/integrations/filter.ts`)
- Listens / handles: `initiateFilterUI`, `filterRangeAlert`, `mouseDown`, `renderFilterCell`, `refreshFilterRange`, `updateSortCollection`, `beforeFltrcMenuOpen`, `filterByCellValue`, `clearFilter`, `getFilteredColumn`, `cMenuBeforeOpen`, `filterDialogCreated`, `filterDialogClose`, `reapplyFilter`, `beforeInsert`, `beforeDelete`, `moveSheetHandler`, `duplicateSheetFilterHandler`, `contentLoaded` and related UI lifecycle events.
- Key handlers:
  - `initiateFilterUIHandler()` — entry for user-driven filter actions and programmatic filter requests; validates range and prepares `FilterOptions`/`PredicateModel[]`.
  - `renderFilterCellHandler()` — renders filter buttons/icons in header cells and attaches popup triggers.
  - `openDialog()` / `initCboxList()` / `initTreeView()` — build filter popup UI, list values, tree-view/checkbox interaction and apply/cancel flow.
  - `filterByCellValueHandler()` — quick filter creation from active cell value (equal predicate).
  - `refreshFilterRange()` — updates header UI and filter buttons after structural changes.
  - `filterSuccessHandler()` / `applyFilter()` — commit predicates to the filter collection and notify core to apply.

## Entry Points (Core)
**Class:** `WorkbookFilter` (`src/workbook/integrations/filter.ts`)
- Listens: `initiateFilter` event.
- Key handlers:
  - `initiateFilterHandler()` — receives `BeforeFilterEventArgs` and either uses provided `FilterOptions.datasource` or calls `getData()` for the sheet range, then delegates to `setFilter()`.
  - `setFilter()` — evaluate DataManager predicates, compute rows to hide/unhide, and call `setRow()` or notify `hideShow` for UI updates (supports virtualization paths).
  - `destroy()` / lifecycle cleanup.

## ASCII Core Logic Flow
User opens filter UI (or selects filter action)
         ↓
`Filter.initiateFilterUIHandler()` validates range → builds `FilterOptions` and `PredicateModel[]`
         ↓
UI calls/dispatches `initiateFilter` event (or core invoked directly) with args and promise
         ↓
`WorkbookFilter.initiateFilterHandler()` fetches data (via `getData` or uses `dataManager`), then calls `setFilter()`
         ↓
`setFilter()` computes `result` (matching rows) with `applyPredicates()` → for rows not matching set `row.hidden = true` and `row.isFiltered = true`
         ↓
If virtualized or large sheet: notify `hideShow` per batch; else call `setRow()` in-place and trigger `renderModule.refreshSheet()` as needed
         ↓
UI `Filter` updates header icons/buttons (`e-filter-btn`), filter popup state and sort/filter menu items; operations are recorded via `beginAction` for undo/redo.

## Operations (functions & responsibilities)
- `initiateFilterUIHandler(args)` (UI)
  - Validate the requested range (`isInValidFilterRange()`), compute effective header and filter range, assemble `eventArgs` and call `parent.notify(initiateFilter, { args, promise })` when applying filters asynchronously.
  - Support options: `predicates`, `range`, `isCut/isInternal`, `useFilterRange`, `allowHeaderFilter`.

- `renderFilterCellHandler(args)` (UI)
  - Create and inject filter button element (`e-filter-btn`) into header cell and attach popup behavior.

- `getPredicateRange(range, predicates, col?)` (UI helper)
  - Return compact predicate address string for incremental predicate application and display.

- `initCboxList()` / `initTreeView()` (UI)
  - Build checkbox list/tree for filter popup, handle selection, search, select-all, and UI state updates.

- `filterByCellValueHandler()` (UI)
  - Convert active cell value into an equality predicate and trigger `initiateFilterUI` flow.

- `applyFilter(filterOptions, range, sheetIdx, prevPredicates, refresh, isInternal)` (UI)
  - Wraps the final step: calls `parent.notify(initiateFilter, ...)` or directly triggers core setFilter depending on sync flags.

- `initiateFilterHandler(eventArgs)` (Core)
  - If `filterOptions.datasource` is provided, use it; otherwise call `getData(this.parent, sheetName!address)` to fetch row JSON.
  - Create a `DataManager` (or use provided) and compute matching rows via `applyPredicates()`.
  - Delegate to `setFilter()` for row hide/unhide actions.

- `setFilter(dataManager, predicates, range, refresh, equalOrPredicates?)` (Core)
  - Uses `applyPredicates` to compute result set; iterates JSON rows and marks non-matching rows as hidden/isFiltered via `setRow()`.
  - For virtualized sheets or large datasets, batch-notify `hideShow` to update UI incrementally and preserve scroll/top-left cell.
  - Triggers `renderModule.refreshSheet()` for final UI repaint when required.

## Validation & Safety
- Range validation: `isInValidFilterRange()` prevents filtering outside of usedRange or on empty sheets.
- Begin/Cancel workflow: `beginAction` event allows cancellation of filter action; `eventArgs.cancel` is respected.
- Promise/async safety: `initiateFilterHandler()` returns/uses a `Deferred.promise` so UI can await data fetch completion (`getData`) before UI updates.
- Virtualization and frozen panes: `setFilter()` distinguishes virtualized vs. normal rendering paths to avoid O(N) DOM updates and preserve viewport and frozen-row/col behavior.
- Structural changes handling: `beforeInsert` / `beforeDelete` / `moveSheetHandler` remove or shift filter metadata safely via helper handlers.
- Undo/Redo: `beginAction` integration ensures filter actions can be recorded; handlers honor `isInternal`/`isCut` flags to avoid double-applying during clipboard moves.

## Desired Outputs

User-facing
- Filter popup with value checklist (checkbox list or tree) and search, custom filter dialog, and Apply/Clear UI.
- Filter icons/buttons in header cells (`e-filter-btn`) showing active status and enabling popup.
- Context-menu and filter-specific sort items integrated into right-click menus.
- Responsive behavior for large data/virtualized sheets with progressive hide/unhide updates.

System-level
- Events & Notifications:
  - UI → Core: `initiateFilter` (apply filter with args + promise)
  - UI local hooks: `initiateFilterUI`, `filterByCellValue`, `reapplyFilter`, `clearFilter`, `getFilteredColumn`, `cMenuBeforeOpen`
  - Core → UI integrations: `hideShow` (batch hide/unhide), `renderModule.refreshSheet()` (refresh), `getData` usage for fetching sheet JSON
  - Action pipeline: `beginAction` for recording filter ops (cancellable)

- Model artifacts:
  - `filterRange` Map (sheetIdx → { useFilterRange, range: number[], allowHeaderFilter }) stored in UI module.
  - `filterCollection` Map (sheetIdx → PredicateModel[]) storing applied predicates.
  - Row state: `RowModel.hidden` and `RowModel.isFiltered` toggled by core `setFilter()`.

- DOM / CSS hooks:
  - Filter button class: `e-filter-btn` and icon `e-filter-icon` / `e-filter-iconbtn`.
  - Popup class: `e-filter-popup` for filter dialog, and `e-spreadsheet-contextmenu` used when adding filter context items.

- Undo/Redo records:
  - Filtering operations are emitted via `beginAction` and can be captured by the workbook action pipeline so filter apply/clear can be undone/redone.

## Implementation Notes (short)
- Keep UI/core separation: `Filter` builds predicates and manages popup UI; `WorkbookFilter` evaluates data and mutates row state.
- Use `DataManager` for performant predicate application and `applyPredicates()` helper to produce the matched set.
- Always validate ranges against `usedRange` and prefer early rejection with `filterRangeAlertHandler()` for invalid requests.
- For virtualized sheets, prefer `hideShow` notifications for incremental updates to avoid full re-renders; call `renderModule.refreshSheet()` only when necessary.
- Ensure `setFilteredCollection()` serializes `filterRange` and `filterCollection` for save/serialize operations.

---