<!--

    Copyright © 2016-2026 The Thingsboard Authors

    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.

-->
<mat-drawer-container hasBackdrop="false" class="tb-absolute-fill">
  @if (entitiesTableConfig.detailsPanelEnabled) {
    <mat-drawer
      class="tb-details-drawer mat-elevation-z4"
      #drawer
      mode="over"
      position="end"
      [opened]="isDetailsOpen">
      <tb-entity-details-panel
        #entityDetailsPanel
        [entitiesTableConfig]="entitiesTableConfig"
        [entityId]="isDetailsOpen ? dataSource.currentEntity?.id : null"
        (closeEntityDetails)="isDetailsOpen = false; detailsPanelOpened.emit(isDetailsOpen);"
        (entityUpdated)="onEntityUpdated($event)"
        (entityAction)="onEntityAction($event)"
        >
      </tb-entity-details-panel>
    </mat-drawer>
  }
  <mat-drawer-content>
    <div class="mat-padding tb-entity-table tb-absolute-fill">
      <div class="tb-entity-table-content tb-outlined-border flex flex-col">
        <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="textSearchMode || !dataSource.selection.isEmpty()">
          <div class="mat-toolbar-tools">
            <div class="title-container flex flex-row items-center justify-start xs:flex-col xs:items-start xs:justify-center">
              @if (entitiesTableConfig.tableTitle) {
                <span class="tb-entity-table-title">{{ entitiesTableConfig.tableTitle }}</span>
              }
              <tb-anchor #entityTableHeader></tb-anchor>
              @if (entitiesTableConfig.useTimePageLink) {
                <tb-timewindow [(ngModel)]="timewindow"
                               (ngModelChange)="onTimewindowChange()"
                asButton strokedButton historyOnly [forAllTimeEnabled]="entitiesTableConfig.forAllTimeEnabled"></tb-timewindow>
              }
            </div>
            <span class="flex-1"></span>
            <div [class.!hidden]="!addEnabled() || entitiesTableConfig.addAsTextButton">
              @if (!entitiesTableConfig.addActionDescriptors.length) {
                <button mat-icon-button
                        [disabled]="isLoading$ | async"
                        (click)="addEntity($event)"
                        matTooltip="{{ translations.add | translate }}"
                        matTooltipPosition="above">
                  <mat-icon>add</mat-icon>
                </button>
              } @else {
                @if (entitiesTableConfig.addActionDescriptors.length === 1) {
                  @if (entitiesTableConfig.addActionDescriptors[0].isEnabled()) {
                    <button
                      mat-icon-button
                      [disabled]="isLoading$ | async"
                      (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)"
                      matTooltip="{{ entitiesTableConfig.addActionDescriptors[0].name }}"
                      matTooltipPosition="above">
                      <tb-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</tb-icon>
                    </button>
                  }
                } @else {
                  <button mat-icon-button [disabled]="isLoading$ | async"
                          matTooltip="{{ translations.add | translate }}"
                          matTooltipPosition="above"
                          [matMenuTriggerFor]="addActionsMenu">
                    <mat-icon>add</mat-icon>
                  </button>
                }
              }
            </div>
            @for (actionDescriptor of headerActionDescriptors; track actionDescriptor) {
              <button mat-icon-button [disabled]="isLoading$ | async"
                      [class.!hidden]="!actionDescriptor.isEnabled()"
                      matTooltip="{{ actionDescriptor.name }}"
                      matTooltipPosition="above"
                      (click)="actionDescriptor.onAction($event)">
                <tb-icon>{{actionDescriptor.icon}}</tb-icon>
              </button>
            }
            <button mat-icon-button [disabled]="isLoading$ | async" (click)="updateData()"
                    matTooltip="{{ 'action.refresh' | translate }}"
                    matTooltipPosition="above">
              <mat-icon>refresh</mat-icon>
            </button>
            @if (entitiesTableConfig.searchEnabled) {
              <button
                mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
                matTooltip="{{ translations.search | translate }}"
                matTooltipPosition="above">
                <mat-icon>search</mat-icon>
              </button>
            }
            <div [class.!hidden]="!addEnabled() || !entitiesTableConfig.addAsTextButton" class="pl-3" style="--mat-fab-small-container-elevation-shadow: none;">
              @if (!entitiesTableConfig.addActionDescriptors.length) {
                <button class="lt-sm:!hidden"
                        mat-flat-button color="primary"
                        [disabled]="isLoading$ | async"
                        (click)="addEntity($event)">
                  <mat-icon>add</mat-icon>
                  {{ translations.add | translate }}
                </button>
                <button class="gt-xs:!hidden"
                        mat-mini-fab color="primary"
                        [disabled]="isLoading$ | async"
                        (click)="addEntity($event)"
                        matTooltip="{{ translations.add | translate }}"
                        matTooltipPosition="above">
                  <mat-icon>add</mat-icon>
                </button>
              } @else {
                @if (entitiesTableConfig.addActionDescriptors.length === 1) {
                  @if (entitiesTableConfig.addActionDescriptors[0].isEnabled()) {
                    <button class="lt-sm:!hidden"
                            mat-flat-button color="primary"
                            [disabled]="isLoading$ | async"
                            (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)">
                      <tb-icon matButtonIcon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</tb-icon>
                      {{ entitiesTableConfig.addActionDescriptors[0].name }}
                    </button>
                    <button class="gt-xs:!hidden"
                            mat-mini-fab color="primary"
                            [disabled]="isLoading$ | async"
                            (click)="entitiesTableConfig.addActionDescriptors[0].onAction($event)"
                            matTooltip="{{ entitiesTableConfig.addActionDescriptors[0].name }}"
                            matTooltipPosition="above">
                      <mat-icon>{{entitiesTableConfig.addActionDescriptors[0].icon}}</mat-icon>
                    </button>
                  }
                } @else {
                  <button class="lt-sm:!hidden"
                          mat-flat-button color="primary"
                          [disabled]="isLoading$ | async"
                          [matMenuTriggerFor]="addActionsMenu">
                    <mat-icon>add</mat-icon>
                    {{ translations.add | translate }}
                  </button>
                  <button class="gt-xs:!hidden"
                          mat-mini-fab color="primary"
                          [disabled]="isLoading$ | async"
                          [matMenuTriggerFor]="addActionsMenu"
                          matTooltip="{{ translations.add | translate }}"
                          matTooltipPosition="above">
                    <mat-icon>add</mat-icon>
                  </button>
                }
              }
            </div>
            <mat-menu #addActionsMenu="matMenu" xPosition="before">
              @for (actionDescriptor of entitiesTableConfig.addActionDescriptors; track actionDescriptor) {
                <button mat-menu-item
                        [disabled]="isLoading$ | async"
                        [class.!hidden]="!actionDescriptor.isEnabled()"
                        (click)="actionDescriptor.onAction($event)">
                  <tb-icon matMenuItemIcon>{{actionDescriptor.icon}}</tb-icon>
                  <span>{{ actionDescriptor.name }}</span>
                </button>
              }
            </mat-menu>
          </div>
        </mat-toolbar>
        <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="!textSearchMode || !dataSource.selection.isEmpty()">
          <div class="mat-toolbar-tools">
            <button mat-icon-button
                    matTooltip="{{ translations.search | translate }}"
                    matTooltipPosition="above">
              <mat-icon>search</mat-icon>
            </button>
            <mat-form-field class="flex-1">
              <mat-label>&nbsp;</mat-label>
              <input #searchInput matInput
                     [formControl]="textSearch"
                     placeholder="{{ translations.search | translate }}"/>
            </mat-form-field>
            <button mat-icon-button (click)="exitFilterMode()"
                    matTooltip="{{ 'action.close' | translate }}"
                    matTooltipPosition="above">
              <mat-icon>close</mat-icon>
            </button>
          </div>
        </mat-toolbar>
        @if (entitiesTableConfig.selectionEnabled) {
          <mat-toolbar class="mat-mdc-table-toolbar" color="primary" [class.!hidden]="dataSource.selection.isEmpty()">
            <div class="mat-toolbar-tools">
              <span class="tb-entity-table-info">
                {{ translations.selectedEntities | translate:{count: dataSource.selection.selected.length} }}
              </span>
              <span class="flex-1"></span>
              @for (actionDescriptor of groupActionDescriptors; track actionDescriptor) {
                <button mat-icon-button [disabled]="isLoading$ | async"
                        [class.!hidden]="!actionDescriptor.isEnabled"
                        matTooltip="{{ actionDescriptor.name }}"
                        matTooltipPosition="above"
                        (click)="actionDescriptor.onAction($event, dataSource.selection.selected)">
                  <tb-icon>{{actionDescriptor.icon}}</tb-icon>
                </button>
              }
            </div>
          </mat-toolbar>
        }
        <div class="table-container flex-1">
          <table mat-table [dataSource]="dataSource" [trackBy]="trackByEntityId"
                 matSort [matSortActive]="pageLink.sortOrder?.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
            <ng-container matColumnDef="select" sticky>
              <mat-header-cell *matHeaderCellDef style="width: 40px;">
                <mat-checkbox (change)="$event ? dataSource.masterToggle() : null"
                              [checked]="dataSource.selection.hasValue() && (dataSource.isAllSelected() | async)"
                              [indeterminate]="dataSource.selection.hasValue() && !(dataSource.isAllSelected() | async)">
                </mat-checkbox>
              </mat-header-cell>
              <mat-cell *matCellDef="let entity">
                <mat-checkbox (click)="$event.stopPropagation()"
                              [class.!hidden]="!entitiesTableConfig.entitySelectionEnabled(entity)"
                              (change)="$event ? dataSource.selection.toggle(entity) : null"
                              [checked]="dataSource.selection.isSelected(entity)">
                </mat-checkbox>
              </mat-cell>
            </ng-container>
            @for (column of entityColumns; track column.key) {
              <ng-container [matColumnDef]="column.key">
                <mat-header-cell [class.mat-number-cell]="column.isNumberColumn"
                                 [class.lt-lg:!hidden]="column.mobileHide"
                                 *matHeaderCellDef [style]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable">
                {{ column.ignoreTranslate ? column.title : (column.title | translate) }} </mat-header-cell>
                <mat-cell [class.mat-number-cell]="column.isNumberColumn"
                          [class.cell-action]="column.actionCell?.type === cellActionType.COPY_BUTTON"
                          [class.lt-lg:!hidden]="column.mobileHide"
                          *matCellDef="let entity; let row = index"
                          [matTooltip]="cellTooltip(entity, column, row)"
                          #cellMatTooltip="matTooltip"
                          matTooltipPosition="above"
                          [style]="cellStyle(entity, column, row)">
                  @switch (column.type) {
                    @case ('link') {
                      @if (column.entityURL(entity); as detailsPageURL) {
                        <a
                          [routerLink]="detailsPageURL" [innerHTML]="cellContent(entity, column, row)"
                        (click)="$event.stopPropagation();"></a>
                      } @else {
                        <span [innerHTML]="cellContent(entity, column, row)"></span>
                      }
                    }
                    @case ('entityChips') {
                      <tb-entity-chips [entity]="entity" [key]="column.key"
                      [detailsPagePrefixUrl]="column.entityURL ? column.entityURL(entity) : ''"></tb-entity-chips>
                    }
                    @default {
                      <span [innerHTML]="cellContent(entity, column, row)"></span>
                    }
                  }
                  @if (column.actionCell) {
                    @switch (column.actionCell.type) {
                      @case (cellActionType.COPY_BUTTON) {
                        <tb-copy-button
                          class="copy-button"
                          [disabled]="isLoading$ | async"
                          [class.!hidden]="!column.actionCell.isEnabled(entity)"
                          [copyText]="column.actionCell.onAction(null, entity)"
                          tooltipText="{{ column.actionCell.nameFunction ? column.actionCell.nameFunction(entity) : column.actionCell.name }}"
                          tooltipPosition="above"
                          (mouseover)="cellMatTooltip.hide()"
                          (mouseleave)="cellMatTooltip.show()"
                          [icon]="column.actionCell.icon"
                          [style]="column.actionCell.style">
                        </tb-copy-button>
                      }
                      @default {
                        <button mat-icon-button [disabled]="isLoading$ | async"
                                [class.!hidden]="!column.actionCell.isEnabled(entity)"
                                matTooltip="{{ column.actionCell.nameFunction ? column.actionCell.nameFunction(entity) : column.actionCell.name }}"
                                matTooltipPosition="above"
                                (click)="column.actionCell.onAction($event, entity)">
                          <tb-icon [style]="column.actionCell.style">
                            {{column.actionCell.icon}}
                          </tb-icon>
                        </button>
                      }
                    }
                  }
                </mat-cell>
              </ng-container>
            }
            @for (column of actionColumns; track trackByColumnKey($index, column)) {
              <ng-container [matColumnDef]="column.key">
                <mat-header-cell *matHeaderCellDef [style]="headerCellStyle(column)" mat-sort-header [disabled]="!column.sortable"> {{ column.title | translate }} </mat-header-cell>
                <mat-cell *matCellDef="let entity; let row = index"
                          [style]="cellStyle(entity, column, row)">
                  <button mat-icon-button [disabled]="isLoading$ | async"
                          [class.!hidden]="!column.actionDescriptor.isEnabled(entity)"
                          matTooltip="{{ column.actionDescriptor.nameFunction ? column.actionDescriptor.nameFunction(entity) : column.actionDescriptor.name }}"
                          matTooltipPosition="above"
                          (click)="column.actionDescriptor.onAction($event, entity)">
                    <tb-icon [style]="column.actionDescriptor.style">
                      {{column.actionDescriptor.iconFunction ? column.actionDescriptor.iconFunction(entity) : column.actionDescriptor.icon}}
                    </tb-icon>
                  </button>
                </mat-cell>
              </ng-container>
            }
            <ng-container matColumnDef="actions" stickyEnd>
              <mat-header-cell *matHeaderCellDef>
                @if (cellActionDescriptors.length) {
                  <div class="gt-md:!hidden" style="min-width: 48px;">
                    {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }}
                  </div>
                  <div class="lt-lg:!hidden"
                       [style.min-width]="(cellActionDescriptors.length * 48) + 'px'">
                    {{ entitiesTableConfig.actionsColumnTitle ? (entitiesTableConfig.actionsColumnTitle | translate) : '' }}
                  </div>
                }
              </mat-header-cell>
              <mat-cell *matCellDef="let entity">
                @if (cellActionDescriptors.length) {
                  <div [class.lt-lg:!hidden]="cellActionDescriptors.length !== 1" class="flex flex-row items-stretch justify-end"
                       [style.min-width]="(cellActionDescriptors.length * 48) + 'px'">
                    @for (actionDescriptor of cellActionDescriptors; track actionDescriptor) {
                      <button mat-icon-button [disabled]="(isLoading$ | async) || !actionDescriptor.isEnabled(entity)"
                              matTooltip="{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}"
                              matTooltipPosition="above"
                              (click)="actionDescriptor.onAction($event, entity)">
                        <tb-icon [style]="actionDescriptor.style">
                          {{actionDescriptor.iconFunction ?  actionDescriptor.iconFunction(entity) : actionDescriptor.icon}}
                        </tb-icon>
                      </button>
                    }
                  </div>
                  <div [class.!hidden]="cellActionDescriptors.length === 1" class="gt-md:!hidden">
                    <button mat-icon-button
                            (click)="$event.stopPropagation()"
                            [matMenuTriggerFor]="cellActionsMenu">
                      <mat-icon class="material-icons">more_vert</mat-icon>
                    </button>
                    <mat-menu #cellActionsMenu="matMenu" xPosition="before">
                      @for (actionDescriptor of cellActionDescriptors; track actionDescriptor) {
                        <button mat-menu-item
                                [disabled]="isLoading$ | async"
                                [class.!hidden]="!actionDescriptor.isEnabled(entity)"
                                (click)="actionDescriptor.onAction($event, entity)">
                          <tb-icon matMenuItemIcon [style]="actionDescriptor.style">
                            {{actionDescriptor.iconFunction ?  actionDescriptor.iconFunction(entity) : actionDescriptor.icon}}
                          </tb-icon>
                          <span>{{ actionDescriptor.nameFunction ? actionDescriptor.nameFunction(entity) : actionDescriptor.name }}</span>
                        </button>
                      }
                    </mat-menu>
                  </div>
                }
              </mat-cell>
            </ng-container>
            <mat-header-row [class.mat-row-select]="selectionEnabled" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
            <mat-row [class.!hidden]="dataSource.dataLoading"
                     [class.mat-row-select]="selectionEnabled"
                     [class.mat-selected]="dataSource.selection.isSelected(entity)"
                     [class.tb-current-entity]="dataSource.isCurrentEntity(entity)"
                     [class.tb-pointer]="entitiesTableConfig.rowPointer"
            *matRowDef="let entity; columns: displayedColumns;" (click)="onRowClick($event, entity)"></mat-row>
          </table>
          <span [class.!hidden]="(isLoading$ | async) || (dataSource.isEmpty() | async) === false || dataSource.dataLoading"
          class="no-data-found flex items-center justify-center">{{ translations.noEntities | translate }}</span>
          <span [class.!hidden]="!dataSource.dataLoading"
          class="no-data-found flex items-center justify-center">{{ 'common.loading' | translate }}</span>
        </div>
        @if (displayPagination) {
          <mat-divider></mat-divider>
        }
        @if (displayPagination) {
          <mat-paginator
            [length]="dataSource.total() | async"
            [pageIndex]="pageLink.page"
            [pageSize]="pageLink.pageSize"
            [pageSizeOptions]="pageSizeOptions"
            [hidePageSize]="hidePageSize"
          showFirstLastButtons></mat-paginator>
        }
      </div>
    </div>
  </mat-drawer-content>
</mat-drawer-container>
