/*
 * Copyright 2026 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { isEqual } from "lodash-es";
import React, { createContext, useContext, useRef } from "react";

/**
 * All user-facing strings rendered by the object table and its
 * sub-components.
 */

export const DEFAULT_OBJECT_TABLE_LABELS = {
  noData: "No Data",
  errorLoadingData: errorMessage => `Error Loading Data: ${errorMessage}`,
  editFooterEditTable: "Edit Table",
  editFooterSubmitEdits: "Submit Edits",
  editFooterCancel: "Cancel",
  editFooterSelectRowToEdit: "Select a row to edit data…",
  editFooterModificationCount: count => `${count} modifications`,
  editFooterValidationError: "Validation error",
  cellValidationError: "Validation error",
  columnConfigTitle: "Configure Table Columns",
  columnConfigCancel: "Cancel",
  columnConfigApply: "Apply",
  columnConfigVisibleColumns: "Visible Columns",
  columnConfigDragToReorder: "Drag to reorder",
  columnConfigAddOrRemoveColumns: "Add or Remove Columns",
  columnConfigAllColumns: "All Columns",
  columnConfigNoVisibleColumns: "No visible columns",
  columnConfigNoMatchingColumns: "No matching columns found",
  columnConfigSearchPlaceholder: "Search...",
  columnConfigSearchAriaLabel: "Search available columns",
  sortDialogTitle: "Sort on Multiple Columns",
  sortDialogCancel: "Cancel",
  sortDialogApply: "Apply",
  sortDialogAddColumnToSort: "Add Column to Sort",
  sortDialogSearchPlaceholder: "Search columns",
  sortDialogNoMatchingColumns: "No matching columns",
  sortDialogToggleDirection: columnName => `Toggle sort direction for ${columnName}`,
  headerMenuPinColumn: "Pin column",
  headerMenuUnpinColumn: "Unpin Column",
  headerMenuSortAscending: "Sort ascending",
  headerMenuSortDescending: "Sort descending",
  headerMenuSortOnMultipleColumns: "Sort on multiple columns",
  headerMenuClearAllSorts: "Clear all sorts",
  headerMenuResetColumnSize: "Reset Column Size",
  headerMenuConfigureColumns: "Configure Columns",
  headerMenuAriaLabel: columnId => `Open header menu for column with id=${columnId}`,
  cellError: "Error",
  cellNoValue: "No value",
  selectAllRows: "Select all rows",
  deselectAllRows: "Deselect all rows",
  selectRow: rowNumber => `Select row ${rowNumber}`
};
const ObjectTableLabelsContext = /*#__PURE__*/createContext(DEFAULT_OBJECT_TABLE_LABELS);
/**
 * Supplies overridden {@link ObjectTableLabels} to descendant table
 * sub-components via context. Merges `labels` over the labels from the nearest
 * ancestor provider, so a wrapping `ObjectTable`/`BaseTable` and an inner
 * dialog can each override a different subset.
 *
 * The provided value keeps a stable identity across renders whenever the
 * merged labels are equal, so callers can pass an inline `labels` object
 * without re-rendering every label consumer.
 */
export function ObjectTableLabelsProvider({
  labels,
  children
}) {
  const parent = useContext(ObjectTableLabelsContext);
  const merged = labels != null ? {
    ...parent,
    ...labels
  } : parent;

  // Reuse the previous value when the merge is equal so an inline `labels`
  // object (new identity each render) doesn't churn the context.
  const stableRef = useRef(merged);
  if (!isEqual(stableRef.current, merged)) {
    stableRef.current = merged;
  }
  return /*#__PURE__*/React.createElement(ObjectTableLabelsContext.Provider, {
    value: stableRef.current
  }, children);
}

/**
 * Returns the fully-resolved {@link ObjectTableLabels} for the current subtree.
 * When no {@link ObjectTableLabelsProvider} is present, returns
 * {@link DEFAULT_OBJECT_TABLE_LABELS}.
 */
export function useObjectTableLabels() {
  return useContext(ObjectTableLabelsContext);
}

/**
 * Wraps `Inner` so it accepts an optional `labels` prop and supplies the merged
 * {@link ObjectTableLabels} to its subtree.
 *
 * For generic components, e.g. `BaseTable` use
 * {@link ObjectTableLabelsProvider} directly to preserve its `TData`
 * type parameter.
 */
export function withObjectTableLabels(Inner) {
  function LabelledComponent(props) {
    const {
      labels,
      ...rest
    } = props;
    return /*#__PURE__*/React.createElement(ObjectTableLabelsProvider, {
      labels: labels
    }, /*#__PURE__*/React.createElement(Inner, rest));
  }
  LabelledComponent.displayName = `withObjectTableLabels(${Inner.displayName})`;
  return LabelledComponent;
}
//# sourceMappingURL=ObjectTableLabels.js.map