@use "sass:math";
@use "sass:map";
@use "../variables" as *;
@use "../maps" as *;
@use "../../util/scss/add-rules.scss" as *;
@use "../../util/scss/clockwise.scss" as *;
@use "../../util/scss/deep-merge.scss" as *;
@use "../../util/scss/calc.scss" as *;
@use "../../util/scss/besm.scss" as *;
@use "../../util/scss/include.scss" as *;

@mixin cx-grid(
   $name: "grid",
   $header-state-style-map: $cx-grid-header-state-style-map,
   $data-state-style-map: $cx-grid-data-state-style-map,
   $cell-cursor-style: $cx-grid-cell-cursor-style,
   $icon-size: $cx-default-icon-size,
   $besm: $cx-besm
) {
   $block: map.get($besm, block);
   $element: map.get($besm, element);
   $state: map.get($besm, state);
   $mod: map.get($besm, mod);

   .#{$block}#{$name} {
      box-sizing: border-box;
      position: relative;
      font-size: $cx-default-grid-font-size;
      box-shadow: $cx-default-grid-box-shadow;
      border-radius: $cx-default-grid-border-radius;

      @include cx-add-state-rules($cx-list, default);

      &:focus {
         @include cx-add-state-rules($cx-list, focus);
      }

      table {
         border-spacing: 0;
         border-collapse: collapse;
         width: 100%;
         position: relative;
         font-size: inherit;
      }

      .#{$state}aligned-left {
         text-align: left;
      }

      .#{$state}aligned-right {
         text-align: right;
      }

      .#{$state}aligned-center {
         text-align: center;
      }

      &.#{$state}scrollable {
         overflow: hidden;
         display: flex;
         flex-direction: row;
         align-items: stretch;

         &.#{$state}border {
            border: 1px solid $cx-default-grid-border-color;
            background: $cx-default-grid-background;

            table {
               border: none;
            }

            .#{$element}#{$name}-header:first-child {
               th {
                  border-top: none;
               }
            }

            th {
               border-left: none;
            }

            th:last-child {
               border-right: none;
            }
         }

         & > .#{$element}#{$name}-scroll-area {
            overflow-y: auto;
            flex: 1 1 0%;
            -webkit-overflow-scrolling: touch;

            &.#{$state}fixed-header
               > .#{$element}#{$name}-table-wrapper
               > table
               > .#{$element}#{$name}-header:first-child {
               visibility: hidden;
            }

            //used to cut off the negative margin
            & > .#{$element}#{$name}-table-wrapper {
               overflow: hidden;
               display: inline-block; //preserve content width
               vertical-align: top;
               min-width: 100%;
               min-height: 100%;
               padding-top: $cx-default-grid-scroll-wrapper-padding-top;
            }
         }
      }

      &.#{$state}resizable {
         .#{$element}#{$name}-data td,
         .#{$element}#{$name}-group-footer td,
         .#{$element}#{$name}-group-header td {
            box-sizing: border-box;
            overflow: hidden;
            text-overflow: ellipsis;
         }

         .cxe-grid-fixed-header .cxe-grid-col-header:last-child {
            max-width: 100%;
            width: 100%;
         }
      }

      &.#{$state}border {
         background: $cx-default-grid-background;

         table {
            border: 1px solid $cx-default-grid-border-color;
         }
      }

      &.#{$state}vlines {
         td:not(:last-child),
         th:not(:last-child) {
            border-right-width: 1px;
            border-right-style: solid;
            border-right-color: $cx-default-grid-border-color;
         }
      }

      &.#{$mod}responsive {
         width: 100%;

         & > .#{$element}#{$name}-scroll-area {
            overflow-x: auto;
         }
      }

      &.#{$mod}fixed-layout {
         table {
            table-layout: fixed;
            width: auto;
         }
      }

      &.#{$mod}contain {
         table {
            contain: layout paint;
         }
      }

      &.#{$mod}nowrap {
         .cxe-grid-data td,
         .cxe-grid-fixed-footer td,
         .cxe-grid-fixed-fixed-footer td {
            white-space: nowrap;
         }
      }
   }

   .#{$element}#{$name}-table-wrapper {
      overflow-anchor: none;
   }

   .#{$element}#{$name}-cell-clip {
      overflow: hidden;
      text-overflow: ellipsis;
   }

   .#{$element}#{$name}-row-number::after {
      counter-increment: cx-row-number;
      content: counter(cx-row-number);
   }

   .#{$element}#{$name}-fixed-header {
      overflow: hidden;
      position: absolute;
      display: none;
      left: 0;
      top: 0;
      right: 0;

      & > table {
         width: auto;
         table-layout: fixed;
      }
   }

   .#{$element}#{$name}-fixed-fixed-header {
      overflow: hidden;
      position: absolute;
      display: none;
      left: 0;
      top: 0;
      box-sizing: border-box;
      border-right: 1px solid $cx-default-grid-border-color;

      & > table {
         width: auto;
         table-layout: fixed;
      }
   }

   .#{$element}#{$name}-fixed-footer {
      overflow: hidden;
      position: absolute;
      display: none;
      left: 0;
      bottom: 0;
      right: 0;

      & > table {
         width: auto;
         table-layout: fixed;
      }
   }

   .#{$element}#{$name}-fixed-fixed-footer {
      overflow: hidden;
      position: absolute;
      display: none;
      left: 0;
      bottom: 0;
      border-right: 1px solid $cx-default-grid-border-color;
      box-sizing: border-box;

      & > table {
         width: auto;
         table-layout: fixed;
      }
   }

   .#{$element}#{$name}-fixed-footer-corner {
      width: 100%;
   }

   .#{$element}#{$name}-empty-text td {
      color: #aaa;
      padding: 2rem;
   }

   .#{$element}#{$name}-col-header {
      text-align: left;
      padding: cx-get-state-rule($data-state-style-map, default, padding);
      box-sizing: border-box;
      position: relative;
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      -webkit-user-select: none;

      @include cx-add-state-rules($header-state-style-map, default);

      .#{$state}header-default & {
         border-width: 1px;
         border-style: solid;
         position: relative;
      }

      .#{$state}header-plain & {
         background-color: transparent;
      }

      &.#{$state}sortable {
         cursor: pointer;
         user-select: none;

         &.#{$state}sorted-asc,
         &.#{$state}sorted-desc {
            @include cx-add-state-rules($header-state-style-map, sorted);

            &:hover {
               @include cx-add-state-rules($header-state-style-map, sorted-hover);
            }
         }

         &:hover,
         .#{$element}#{$name}-fixed-header &:hover {
            @include cx-add-state-rules($header-state-style-map, hover);
         }

         .#{$element}#{$name}-fixed-header & {
            &.#{$state}sorted-asc,
            &.#{$state}sorted-desc {
               &:hover {
                  @include cx-add-state-rules($header-state-style-map, sorted-hover);
               }
            }
         }
      }

      &.#{$state}tool {
         transition: padding-left 0.2s;
         padding-right: cx-calc(15px, $icon-size);
      }

      &.#{$state}sortable:not(.#{$state}aligned-right) {
         padding-right: cx-calc(5px, $icon-size);

         .#{$element}#{$name}-column-sort-icon {
            right: 2px;
         }

         &.#{$state}tool.#{$state}sorted-asc,
         &.#{$state}tool.#{$state}sorted-desc {
            padding-left: cx-calc(5px, $icon-size);

            .#{$element}#{$name}-column-sort-icon {
               left: 2px;
            }
         }
      }

      &.#{$state}sortable.#{$state}aligned-center {
         padding-left: cx-calc(5px, $icon-size);
      }

      &.#{$state}sortable.#{$state}aligned-right {
         padding-left: cx-calc(5px, $icon-size);

         .#{$element}#{$name}-column-sort-icon {
            left: 2px;
         }
      }
   }

   .#{$element}#{$name}-column-sort-icon {
      width: $icon-size;
      height: $icon-size;
      top: 50%;
      margin-top: cx-multiply($icon-size, -0.5);
      position: absolute;
      transition: transform 0.1s linear;

      .#{$state}sorted-desc > & {
         transform: rotate(180deg);
      }
   }

   .#{$element}#{$name}-data {
      -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
      background-color: cx-get-state-rule($data-state-style-map, default, background-color);

      &.#{$state}alternate {
         @include cx-add-state-rules($data-state-style-map, alternate);
      }

      td {
         padding: 0;
         border-top: 1px solid cx-get-state-rule($data-state-style-map, default, border-color);
         line-height: cx-get-state-rule($data-state-style-map, default, line-height);
         font-weight: cx-get-state-rule($data-state-style-map, default, font-weight);
         font-size: cx-get-state-rule($data-state-style-map, default, font-size);

         &:empty::before {
            content: "-";
            visibility: hidden;
         }
      }

      td.#{$state}pad {
         padding: cx-get-state-rule($data-state-style-map, default, padding);
      }

      .#{$state}selectable & {
         &:hover,
         &.#{$state}hover {
            @include cx-add-state-rules($data-state-style-map, hover);
         }

         &.#{$state}cursor {
            @include cx-add-state-rules($data-state-style-map, hover);
         }

         &.#{$state}selected {
            @include cx-add-state-rules($data-state-style-map, selected);

            &.#{$state}cursor {
               @include cx-add-state-rules($data-state-style-map, selected-cursor);
            }
         }
      }

      .#{$state}focused &,
      :focus & {
         &.#{$state}cursor {
            @include cx-add-state-rules($data-state-style-map, cursor);
         }

         &.#{$state}selected {
            &.#{$state}cursor {
               @include cx-add-state-rules($data-state-style-map, selected-cursor);
            }
         }

         &:active {
            @include cx-add-state-rules($data-state-style-map, active);
         }
      }

      .#{$state}drag-move &.#{$state}dragged {
         display: none;
      }

      .#{$state}drag-copy &.#{$state}dragged {
         opacity: 0.5;
      }

      &.#{$state}draggable {
         touch-action: none;
      }

      &.#{$state}dummy {
         td {
            box-sizing: border-box;
         }
      }

      &.#{$state}over {
         background: orange !important;
      }
   }

   .#{$element}#{$name}-dropzone {
      position: relative;
      padding: 0;

      .#{$state}drop-preview & {
         border-top: 1px solid $cx-default-grid-border-color;

         &:after {
            position: absolute;
            left: 3px;
            right: 3px;
            top: 3px;
            bottom: 3px;
            border: 1px dotted gray;
            content: " ";
         }
      }

      .#{$state}drop-insertion & {
         height: 0;

         &:after {
            position: absolute;
            left: 0;
            right: 0;
            top: 0;
            bottom: 0;
            border-top: 1px solid black;
            content: " ";
            box-shadow: 0 0 2px black;
         }
      }
   }

   .#{$element}#{$name}-group-caption {
      font-weight: bold;

      td {
         padding: cx-get-state-rule($data-state-style-map, default, padding);
      }

      &:not(:first-child) {
         td {
            padding-top: $cx-default-grid-caption-gap;
         }
      }
   }

   @for $i from 1 through 4 {
      .#{$element}#{$name}-group-caption.#{$state}level-#{$i} td {
         @include cx-add-state-rules($cx-grid-group-caption-level-style-map, level-#{$i});
      }
   }

   .#{$element}#{$name}-group-footer {
      td {
         box-sizing: border-box;
         &.#{$state}pad {
            padding: cx-get-state-rule($data-state-style-map, default, padding);
         }
      }
   }

   @for $i from 1 through 4 {
      .#{$element}#{$name}-group-footer.#{$state}level-#{$i} td {
         @include cx-add-state-rules($cx-grid-group-footer-level-style-map, level-#{$i});
      }
   }

   .#{$block}#{$name}.#{$state}cell-editable {
      .#{$element}#{$name}-data td {
         &:hover {
            background: rgba(gray, 0.05);
         }

         &.#{$state}cellected {
            position: relative;
            user-select: none;
            overflow: visible;

            &:after {
               position: absolute;
               pointer-events: none;
               content: " ";
               @include cx-add-rules($cell-cursor-style);
            }

            &:last-child::after {
               //prevent horizontal scroll for fixed columns
               right: 0;
            }
         }

         &.#{$element}#{$name}-cell-editor {
            position: relative;
            user-select: none;
            overflow: visible;
         }
      }
   }

   .#{$element}#{$name}-cell-editor-wrap {
      position: absolute;
      top: -1px;
      bottom: 0;
      left: 0;
      right: 0;
      width: 100%;
      height: calc(100% + 2px);

      & > *:only-child {
         width: 100%;
         height: 100%;
         top: 0;
         left: 0;
      }
   }

   .#{$block}#{$name}.#{$state}buffered,
   .#{$block}#{$name}.#{$state}fixed-columns {
      .#{$element}#{$name}-data {
         white-space: nowrap;
      }
   }

   .#{$block}#{$name}.#{$state}fixed-columns {
      > .#{$element}#{$name}-scroll-area {
         overflow-x: scroll;
      }
   }

   .#{$element}#{$name}-scroll-area {
      &.#{$state}fixed-footer
         > .#{$element}#{$name}-table-wrapper
         > table
         > .#{$element}#{$name}-group-footer:last-child {
         visibility: hidden;

         td {
            border: none;
         }
      }
   }

   .#{$element}#{$name}-fixed-scroll-area {
      overflow-x: scroll;
      overflow-y: hidden;
      border-color: $cx-default-grid-border-color;
      border-right-style: solid;
      border-right-width: 1px;

      & > .#{$element}#{$name}-fixed-table-wrapper {
         padding-top: $cx-default-grid-scroll-wrapper-padding-top;
      }

      &.#{$state}fixed-footer
         > .#{$element}#{$name}-fixed-table-wrapper
         > table
         > .#{$element}#{$name}-group-footer:last-child {
         visibility: hidden;

         td {
            border: none;
         }
      }
   }

   .#{$element}#{$name}-col-header-tool {
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
   }

   .#{$element}#{$name}-col-resizer {
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
      width: 5px;
      cursor: col-resize;
   }

   .#{$element}#{$name}-col-resizer-prev-col {
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      width: 5px;
      cursor: col-resize;
   }

   .#{$element}#{$name}-resize-overlay {
      position: absolute;
      display: block;
      pointer-events: none;
      top: 0;
      bottom: 0;
      left: 0;
      width: 0;
      border-right: 3px solid $cx-default-grid-border-color;
      background: color-mix(in srgb, $cx-default-grid-border-color 15%, transparent);
      box-sizing: border-box;
   }

   .#{$element}#{$name}-col-header-drag-clone {
      border: 1px solid $cx-default-grid-border-color;
      padding: cx-get-state-rule($data-state-style-map, default, padding);
      @include cx-add-state-rules($header-state-style-map, default);
      box-sizing: border-box;
      font-size: $cx-default-grid-font-size;
   }

   .#{$element}#{$name}-col-insertion-marker {
      border: 1px solid black;
      position: absolute;
      top: 0;
      height: calc(100% - 1px);
   }
}

@if (cx-should-include("cx/widgets/Grid")) {
   @include cx-grid();
}
