/*
 * This file belongs to Hoist, an application development toolkit
 * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
 *
 * Copyright © 2026 Extremely Heavy Industries Inc.
 */

@mixin group-border($side) {
  border-#{$side}: var(--xh-border-solid);
}

@mixin pinned-border($side) {
  border-#{$side}: 1px solid var(--xh-grid-pinned-column-border-color);
}

// Ag-grid installs an outer div around itself.
.xh-ag-grid > div {
  width: 100%;
}

.xh-mobile {
  // ag-grid adds these when the center viewport has overflow, so that the space taken by the scrollbar is consistent in
  // the top and bottom floating divs. On mobile we do not render scrollbars for the center viewport, so force hiding
  // in the top and bottom floating divs.
  .ag-floating-top,
  .ag-floating-bottom {
    overflow-y: hidden !important;
  }

  // Prevent the "bounce" overscroll effect for horizontal scrolling on mobile devices, as it
  // conflicts with the drag management in the Navigator.
  .ag-center-cols-viewport {
    overscroll-behavior-x: none;
  }
}

// Ag-Grid themes referenced here to help ensure a high enough level of specificity for our rules.
// Note DataView excluded from these style customizations to give those views control over their
// component-based item styling w/o being affected by default grid styles / sizing modes.
// Please review DataView.scss when adjusting these styles, however, as some have been carried over
// or modified for use with that component.
*:not(.xh-data-view) > .ag-theme-balham.xh-ag-grid,
*:not(.xh-data-view) > .ag-theme-balham-dark.xh-ag-grid {
  // Bind ag-grid's base bg to Hoist's grid bg - prevents balham-dark default bleeding through.
  --ag-background-color: var(--xh-grid-bg);

  color: var(--xh-grid-text-color);
  font-family: var(--xh-grid-font-family);
  font-size: var(--xh-grid-font-size-px);

  // ensure ag-grid box-sizing rule is not overridden by
  // body.xh-app box-sizing: inherit
  [class^='ag-'],
  [class^='ag-']:focus,
  [class^='ag-']:after,
  [class^='ag-']:before {
    box-sizing: border-box;
  }

  // using content-box here rather than border-box increases the height of
  // the floating top just enough to prevent bleeding through of underlying rows
  // as user scrolls down.
  .ag-floating-top {
    box-sizing: content-box;
  }

  .ag-root-wrapper {
    background-color: var(--xh-grid-bg);
    // Remove default outer border - we usually render grids in bordered components such as panels.
    border: none;
  }

  // This ensures that rows will take up at least the full width of the grid in cases where there
  // is no horizontal scrollbar.
  .ag-center-cols-container {
    min-width: 100%;
  }

  //------------------------
  // Core Header Classes
  //------------------------
  .ag-header {
    background-color: var(--xh-grid-header-bg);
    border-color: var(--xh-grid-header-border-color);
    font-family: var(--xh-grid-header-font-family);

    .ag-header-row {
      font-size: var(--xh-grid-header-font-size-px);
      font-weight: var(--xh-grid-header-font-weight);
      color: var(--xh-grid-header-text-color);
    }
  }
  &--hide-headers .ag-header {
    display: none;
  }

  //------------------------
  // Core Row Classes
  //------------------------
  .ag-row {
    background-color: var(--xh-grid-bg);
    color: var(--xh-grid-text-color);

    // Selected row styling.
    &.ag-row-selected {
      background-color: var(--xh-grid-selected-row-bg);
      .ag-cell {
        color: var(--xh-grid-selected-row-text-color);
      }
    }

    &.ag-row-group.ag-full-width-row {
      color: var(--xh-grid-group-text-color);
      background-color: var(--xh-grid-group-bg);

      .ag-group-expanded,
      .ag-group-contracted {
        color: var(--xh-grid-group-text-color);
      }
    }

    // Set a constant width, since the two icons are different sizes.
    // This caused rows to jump around when expansion was toggled.
    .ag-group-expanded,
    .ag-group-contracted {
      margin: 0;
      width: var(--xh-grid-tree-indent);

      svg {
        width: var(--xh-grid-tree-icon-px) !important;
      }
    }
  }

  // Docked summary
  .ag-floating-top,
  .ag-floating-bottom {
    border-color: var(--xh-grid-summary-row-border-color);
  }

  // Row borders
  &--row-borders {
    .ag-row {
      border-color: var(--xh-grid-border-color);

      // Apply `--xh-grid-group-border-color` var to full-width grouped rows - for tree grid groups,
      // see the dedicated `--xh-grid-tree-group-border-color` var, applied within Grid.scss.
      &.ag-row-group.ag-full-width-row {
        border-color: var(--xh-grid-group-border-color);
      }
    }
    .ag-cell {
      border-bottom: none;
      border-top: none;
    }
  }

  &--no-row-borders {
    .ag-row {
      border-bottom: none;
      border-top: none;
    }

    // Deliberately keep border on full-width grouped rows even when we aren't adding row borders.
    // Without this collapsed groups (which don't stripe) blend together in a solid block.
    .ag-row.ag-row-group.ag-full-width-row {
      border-bottom: 1px solid var(--xh-grid-group-border-color);
      border-top: 1px solid var(--xh-grid-group-border-color);
    }
  }

  // Suppress default border on last row for full-width group rows - avoids minor up/down shift
  // when collapsing and expanding the last group.
  .ag-row.ag-row-group.ag-full-width-row.ag-row-last {
    border-bottom-width: 0;
  }

  // Row zebra striping
  &--stripe-rows {
    .ag-row.ag-row-odd:not(.ag-full-width-row):not(.ag-row-selected) {
      background-color: var(--xh-grid-bg-odd);
    }
  }

  // When striping disabled, remove default ag-Grid striping.
  &--no-stripe-rows {
    .ag-row.ag-row-odd:not(.ag-full-width-row):not(.ag-row-selected) {
      background-color: unset;
    }
  }

  // Hover highlight
  &--show-hover {
    .ag-row.ag-row-hover:not(.ag-full-width-row):not(.ag-row-selected):not(.ag-row-pinned) {
      background-color: var(--xh-grid-bg-hover);
    }
  }

  // Disable native ag-grid hover and selection colors
  .ag-row-hover:not(.ag-full-width-row)::before,
  .ag-row-hover.ag-full-width-row.ag-row-group::before,
  .ag-row-hover.ag-row-selected::before,
  .ag-row-selected::before {
    background: none;
  }

  //------------------------
  // Core Cell Classes
  //------------------------
  .ag-cell {
    padding-left: var(--xh-grid-cell-lr-pad-px);
    padding-right: var(--xh-grid-cell-lr-pad-px);
  }

  .ag-header-cell,
  .ag-header-group-cell {
    padding-left: var(--xh-grid-header-lr-pad-px);
    padding-right: var(--xh-grid-header-lr-pad-px);

    // Override ag-Grid defaults for the header separator to make it responsive to different header heights
    &::after {
      height: 50%;
      margin-top: unset;
      top: unset;
    }
  }

  .ag-cell {
    &.ag-cell-last-left-pinned:not(.ag-cell-focus) {
      @include pinned-border(right);
    }

    &.ag-cell-first-right-pinned:not(.ag-cell-focus) {
      @include pinned-border(left);
    }
  }

  // We use flexbox to consistently vertically center cell contents across
  // the different sizing modes. See https://github.com/xh/hoist-react/issues/1949
  .ag-cell-value {
    display: flex;
    align-items: center;

    // This ensures the cell's inner-wrapper fills the entire width of the cell,
    // and the text properly ellides. The min-width: 0 is required to enable
    // the flex-child to overflow, as by default flex children take up as much
    // width as necessary to fit their contents.
    // See https://makandracards.com/makandra/66994-css-flex-and-min-width
    .xh-cell-inner-wrapper {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      min-width: 0;
    }
    .ag-row-group {
      align-items: center;
    }
  }

  // Cell borders
  &--cell-borders {
    .ag-cell {
      border-right-color: var(--xh-grid-border-color);
      border-bottom-color: var(--xh-grid-border-color);
    }

    .ag-row {
      border-color: var(--xh-grid-border-color);
    }
  }

  &--no-cell-borders {
    .ag-cell,
    .ag-context-menu-open .ag-cell-focus:not(.ag-cell-range-selected) {
      // Preserve left and right borders to avoid jumpiness upon cell focus
      border-top: none;
      border-bottom: none;
      border-left-color: transparent;
      border-right-color: transparent;
    }
  }

  // Cell focus
  &--no-cell-focus {
    // Preserve cell borders when enabled upon "invisible" cell focus
    &.xh-ag-grid--cell-borders .ag-has-focus .ag-cell-focus:not(.ag-cell-range-selected) {
      border-right-color: var(--xh-grid-border-color);
    }

    .ag-has-focus {
      .ag-cell-focus:not(.ag-cell-range-selected) {
        // Preserve left and right borders to avoid jumpiness upon cell focus
        border-top: none;
        border-bottom: none;
        border-left-color: transparent;
        border-right-color: transparent;

        &.ag-cell {
          &.ag-cell-last-left-pinned {
            @include pinned-border(right);
          }

          &.ag-cell-first-right-pinned {
            @include pinned-border(left);
          }

          &.xh-cell--group-border-left {
            @include group-border(left);
          }

          &.xh-cell--group-border-right {
            @include group-border(right);
          }
        }
      }
    }
  }

  &--show-cell-focus {
    .ag-cell-focus:focus-within {
      border-color: var(--xh-grid-cell-focus-border-color) !important;
    }
  }

  // Change highlighting
  .ag-cell-data-changed {
    background-color: var(--xh-grid-cell-change-bg-highlight) !important;
  }

  //------------------------
  // Large Sizing Mode
  //------------------------
  &--large {
    font-size: var(--xh-grid-large-font-size-px);

    .ag-header .ag-header-row {
      font-size: var(--xh-grid-large-header-font-size-px);
    }

    .ag-cell {
      padding-left: var(--xh-grid-large-cell-lr-pad-px);
      padding-right: var(--xh-grid-large-cell-lr-pad-px);
    }

    .ag-header-cell,
    .ag-header-group-cell {
      padding-left: var(--xh-grid-large-header-lr-pad-px);
      padding-right: var(--xh-grid-large-header-lr-pad-px);
    }
  }

  //------------------------
  // Compact Sizing Mode
  //------------------------
  &--compact {
    font-size: var(--xh-grid-compact-font-size-px);

    .ag-header .ag-header-row {
      font-size: var(--xh-grid-compact-header-font-size-px);
    }

    .ag-cell {
      padding-left: var(--xh-grid-compact-cell-lr-pad-px);
      padding-right: var(--xh-grid-compact-cell-lr-pad-px);
    }

    .ag-header-cell,
    .ag-header-group-cell {
      padding-left: var(--xh-grid-compact-header-lr-pad-px);
      padding-right: var(--xh-grid-compact-header-lr-pad-px);
    }
  }

  //------------------------
  // Tiny Sizing Mode
  //------------------------
  &--tiny {
    font-size: var(--xh-grid-tiny-font-size-px);

    .ag-header .ag-header-row {
      font-size: var(--xh-grid-tiny-header-font-size-px);
    }

    .ag-cell {
      padding-left: var(--xh-grid-tiny-cell-lr-pad-px);
      padding-right: var(--xh-grid-tiny-cell-lr-pad-px);
    }

    .ag-header-cell,
    .ag-header-group-cell {
      padding-left: var(--xh-grid-tiny-header-lr-pad-px);
      padding-right: var(--xh-grid-tiny-header-lr-pad-px);
    }
  }

  //------------------------
  // Other Optional Modifiers + Overrides
  //------------------------
  // As of agGrid 20, the group row always reserve space for a grouping checkbox.
  // We remove this to tighten up the spacing.
  .ag-group-checkbox.ag-invisible {
    display: none;
  }

  // Restore right border on cells - not included by default with ag-grid but
  // causes right-aligned content to shift by one pixel when focused.
  .ag-cell.ag-cell-no-focus {
    border-right: 1px solid transparent;
  }

  // Hiding borders on typically-collapsed accessory panels. This avoids unexpected borders on the
  // right and bottom edges of the grids. Custom grids that wish to use these panels will likely
  // want to override and restore borders.
  .ag-side-bar {
    border: none;
  }

  .ag-status-bar {
    border: none;
  }

  // Disabling the "row loading" render overlay
  .ag-bl-overlay {
    display: none;
  }

  // Adds padding to select all checkbox option in column set filter
  .ag-set-filter-select-all {
    padding: var(--xh-pad-half-px) 0;
  }

  //------------------------
  // Overlay masks
  //------------------------
  .ag-overlay {
    // Match loading overlay color to mask, suppress display of text in center.
    .ag-overlay-loading-wrapper {
      background-color: var(--xh-mask-bg);

      .ag-overlay-loading-center {
        display: none;
      }
    }

    // Reduce default contrast of emptyText.
    .ag-overlay-no-rows-wrapper {
      color: var(--xh-grid-empty-text-color);
    }
  }

  // Set Blueprint controls - specifically checkboxes - to match grid size.
  .bp6-control .bp6-control-indicator {
    font-size: 1em;
  }
}

//------------------------
// Tree Mode
//------------------------
.xh-grid--hierarchical:not(.xh-data-view) > .ag-theme-balham.xh-ag-grid,
.xh-grid--hierarchical:not(.xh-data-view) > .ag-theme-balham-dark.xh-ag-grid {
  // Vertically center tree grid affordances
  .ag-row .ag-cell-wrapper.ag-row-group {
    align-items: center;
  }
}

body.xh-app {
  // Ensure ag-grid popups (context menus, tooltips, and column filter controls) with default z-index of 5
  // appear over bp dialogs with z-index of 20.
  .ag-theme-balham.ag-popup,
  .ag-theme-balham-dark.ag-popup {
    .ag-popup-child {
      z-index: 30;
    }
    .ag-popup-editor {
      background: var(--xh-grid-bg);
    }
  }

  //------------------------
  // Context Menu
  //------------------------
  .ag-theme-balham .ag-menu,
  .ag-theme-balham-dark .ag-menu {
    font-family: var(--xh-font-family);
    font-size: var(--xh-menu-item-font-size-px);
    color: var(--xh-menu-item-text-color);

    // Minimal/high-contrast bg
    background-color: var(--xh-menu-bg);
    border: var(--xh-menu-border);

    // Matching box-shadow of Blueprint context menu popover
    box-shadow:
      0 0 0 1px rgba(16, 22, 26, 0.2),
      0 2px 4px rgba(16, 22, 26, 0.4),
      0 8px 24px rgba(16, 22, 26, 0.4);

    .ag-menu-option.ag-menu-option-active {
      background-color: var(--xh-menu-item-highlight-bg);
    }

    .ag-menu-option-icon {
      text-align: center;
      padding-left: 8px;
      padding-right: 8px;
    }

    // Mute the shortcut text to keep focus on the actual option text
    .ag-menu-option-shortcut {
      color: var(--xh-text-color-muted);
    }

    // Keep the submenu caret in the standard text color
    .ag-menu-option-popup-pointer {
      color: var(--xh-menu-item-text-color);
    }
  }
}
