<template>
  <div
    :class="[
      componentClass,
      visibleColFieldsLockedLeft.length > 0 && 'c-cols-locked-left',
      visibleColFieldsLockedRight.length > 0 && 'c-cols-locked-right',
      { 'c-aggrs': hasAggrFields4Display }
    ]"
    :style="{
      '--c-rows-scroll-width': rowsScrollBarWidthPx,
      '--c-rows-scroll-height': rowsScrollBarHeightPx,
      '--c-rows-headers-width': rowsHeadersWidth + 'px'
    }"
    @keyup="onKeyUp"
    v-resize="handleResize"
    tabindex="0"
  >
    <c-context-menu 
      ref="contextMenu"
      :appWindowIdent="appWindowIdent"
      :dataSetIdent="dataSetIdent"
    >
      <slot name="contextmenu" :row="currentRow" />
    </c-context-menu>
    <div class="c-settings-content" v-if="settingsVisible">
      <div class="c-settings-tabs">
        <div
          class="c-settings-tab"
          :class="{ 'c-active': settingsTabSelected === 1 }"
          v-on:click="settingsTabSelected = 1"
        >Układ danych</div>
        <div
          class="c-settings-tab"
          :class="{ 'c-active': settingsTabSelected === 2 }"
          v-on:click="settingsTabSelected = 2"
        >Sortowanie</div>
        <div
          class="c-settings-tab"
          :class="{ 'c-active': settingsTabSelected === 3 }"
          v-on:click="settingsTabSelected = 3"
        >Agregaty</div>
        <div
          class="c-settings-tab"
          :class="{ 'c-active': settingsTabSelected === 4 }"
          v-on:click="settingsTabSelected = 4"
        >Eksporty</div>
      </div>
      <div class="c-settings-btn-close" v-on:click="settingsVisibleChange">Zamknij</div>

      <div class="c-settings-layout-area" v-if="settingsTabSelected === 1">
        <div class="c-settings-cols">
          <div>
            <div>Kolumny</div>
            <div
              class="c-btn c-settings-action"
              title="Zaznacz wszystko"
              v-on:click="setColFieldsVisibilityAll($event, 1)"
            >&#xe921;</div>
            <div
              class="c-btn c-settings-action"
              title="Odznacz wszystko"
              v-on:click="setColFieldsVisibilityAll($event, 0)"
            >&#xe920;</div>
            <div
              class="c-btn c-settings-action"
              title="Odwróć zaznaczenie"
              v-on:click="reverseColFieldsVisibility()"
            >&#xe922;</div>
            <div
              class="c-btn c-up-btn"
              v-on:click="isFirstColField || colFieldsLockedDefault.length === 0 ? null : colFieldUp()"
              v-bind:class="{ 'c-inactive': isFirstColField || colFieldsLockedDefault.length === 0 }"
            >&#xe91c;</div>
            <div
              class="c-btn"
              v-on:click="isLastColField || colFieldsLockedDefault.length === 0 ? null : colFieldDown()"
              v-bind:class="{ 'c-inactive': isLastColField || colFieldsLockedDefault.length === 0 }"
            >&#xe91b;</div>
          </div>
          <draggable 
            class="c-settings-list"
            v-bind="dragOptions"
            @start="onDragStartColFieldLockedDefault"
            @end="onDragEndColFieldLockedDefault"
          >
            <transition-group type="transition" name="c-settings-list" tag="div" class="c-locks-default">
              <div
                v-for="colField in colFieldsLockedDefault"
                :key="colField.dataFieldIdent"
                :class="['c-settings-list-item', { 'c-active': colField === currentColField }]"
                @click="onClickColField($event, colField)"
              >
                <input
                  type="checkbox"
                  :id="colField.dataFieldIdent"
                  :checked="colField.isVisible"
                  v-on:change="onColFieldVisibleChange($event, colField)"
                />
                <label class="c-checkbox" :for="colField.dataFieldIdent" />
                <div>{{ colField.dataFieldColTranslatedDesc }}</div>
              </div>
            </transition-group>
          </draggable>
        </div>
        <div class="c-settings-actions-vertical">
          <div class="c-settings-actions-locks-left">
            <div
              class="c-right-btn c-locks-left c-btn"
              v-on:click="addColFieldLockedLeft()"
              v-bind:class="{ 'c-inactive': colFieldsLockedDefault.length === 0 }"
            >&#xe919;</div>
            <div
              class="c-left-btn c-locks-left c-btn"
              v-on:click="removeColFieldLockedLeft()"
              v-bind:class="{ 'c-inactive': colFieldsLockedLeft.length === 0 }"
            >&#xe91a;</div>
          </div>
          <div class="c-settings-actions-locks-right">
            <div
              class="c-right-btn c-locks-right c-btn"
              v-on:click="addColFieldLockedRight()"
              v-bind:class="{ 'c-inactive': colFieldsLockedDefault.length === 0 }"
            >&#xe919;</div>
            <div
              class="c-left-btn c-locks-right c-btn"
              v-on:click="removeColFieldLockedRight()"
              v-bind:class="{ 'c-inactive': colFieldsLockedRight.length === 0 }"
            >&#xe91a;</div>
          </div>
        </div>
        <div class="c-settings-locks">
          <div class="c-settings-actions-locks c-locks-left">
            <div>Przypięte do lewej</div>
            <div
              class="c-up-btn c-btn"
              v-on:click="isFirstColFieldLockedLeft || colFieldsLockedLeft.length === 0 ? null : colFieldLockedLeftUp()"
              v-bind:class="{ 'c-inactive': isFirstColFieldLockedLeft || colFieldsLockedLeft.length === 0 }"
            >&#xe91c;</div>
            <div
              class="c-down-btn c-btn"
              v-on:click="isLastColFieldLockedLeft || colFieldsLockedLeft.length === 0 ? null : colFieldLockedLeftDown()"
              v-bind:class="{ 'c-inactive': isLastColFieldLockedLeft || colFieldsLockedLeft.length === 0 }"
            >&#xe91b;</div>
          </div>
          <draggable 
            class="c-settings-list c-locks-left"
            v-bind="dragOptions"
            @start="onDragStartColFieldLockedLeft"
            @end="onDragEndColFieldLockedLeft"
          >
            <transition-group type="transition" name="c-settings-list" tag="div" class="c-locks-left">
              <div
                v-for="colField in colFieldsLockedLeft"
                :key="colField.dataFieldIdent"
                :class="['c-settings-list-item', { 'c-active': colField === currentColFieldLockedLeft }]"
                @click="onClickColFieldLockedLeft($event, colField)"
              >
                <input
                  type="checkbox"
                  :id="colField.dataFieldIdent"
                  :checked="colField.isVisible"
                  v-on:change="onColFieldVisibleChange($event, colField)"
                />
                <label class="c-checkbox" :for="colField.dataFieldIdent" />
                <div>{{ colField.dataFieldColTranslatedDesc }}</div>
              </div>
            </transition-group>
          </draggable>
          <div class="c-settings-actions-locks c-locks-right">
            <div>Przypięte do prawej</div>
            <div
              class="c-up-btn c-btn"
              v-on:click="isFirstColFieldLockedRight || colFieldsLockedRight.length === 0 ? null : colFieldLockedRightUp()"
              v-bind:class="{ 'c-inactive': isFirstColFieldLockedRight || colFieldsLockedRight.length === 0 }"
            >&#xe91c;</div>
            <div
              class="c-down-btn c-btn"
              v-on:click="isLastColFieldLockedRight || colFieldsLockedRight.length === 0 ? null : colFieldLockedRightDown()"
              v-bind:class="{ 'c-inactive': isLastColFieldLockedRight || colFieldsLockedRight.length === 0 }"
            >&#xe91b;</div>
          </div>
          <draggable 
            class="c-settings-list c-locks-right"
            v-bind="dragOptions"
            @start="onDragStartColFieldLockedRight"
            @end="onDragEndColFieldLockedRight"
          >
            <transition-group type="transition" name="c-settings-list" tag="div" class="c-locks-right">
              <div
                v-for="colField in colFieldsLockedRight"
                :key="colField.dataFieldIdent"
                draggable="true"
                :class="['c-settings-list-item', { 'c-active': colField === currentColFieldLockedRight }]"
                @click="onClickColFieldLockedRight($event, colField)"
              >
                <input
                  type="checkbox"
                  :id="colField.dataFieldIdent"
                  :checked="colField.isVisible"
                  v-on:change="onColFieldVisibleChange($event, colField)"
                />
                <label class="c-checkbox" :for="colField.dataFieldIdent" />
                <div>{{ colField.dataFieldColTranslatedDesc }}</div>
              </div>
            </transition-group>
          </draggable>
        </div>
      </div>

      <div class="c-settings-layout-area" v-if="settingsTabSelected === 2">
        <div class="c-settings-cols">
          <div>
            <div>Kolumny</div>
          </div>
          <div 
            class="c-settings-list"
            @dragover.prevent
            @drop.prevent="colFieldDropOnList"
          >
            <div
              v-for="colField in colFields"
              :key="colField.dataFieldIdent"
              :draggable="!isSortColFieldExists(colField)"
              :class="['c-settings-list-item', { 'c-active': colField === currentColField, 'c-disabled': isSortColFieldExists(colField) }]"
              @click="!isSortColFieldExists(colField) ? onClickColField($event, colField) : null"
              @dragstart="onDragStartColField($event, colField)"
              @dragend="onDragEndColField"
              @drop.prevent.stop="colFieldDrop"
            >
              <div>{{ colField.dataFieldColTranslatedDesc }}</div>
            </div>
          </div>
        </div>
        <div class="c-settings-actions-vertical">
          <div
            class="c-right-btn c-btn"
            v-on:click="isSortColFieldExists(currentColField) ? null : addSortColField()"
            v-bind:class="{ 'c-inactive': isSortColFieldExists(currentColField) }"
          >&#xe919;</div>
          <div
            class="c-left-btn c-btn"
            v-on:click="sortColFields.length === 0 ? null : removeSortColField()"
            v-bind:class="{ 'c-inactive': sortColFields.length === 0 }"
          >&#xe91a;</div>
        </div>
        <div class="c-settings-sortings">
          <div>
            <div>Sortowanie</div>
            <div
              class="c-up-btn c-btn"
              v-on:click="isFirstSortColField || sortColFields.length === 0 ? null : sortColFieldUp()"
              v-bind:class="{ 'c-inactive': isFirstSortColField || sortColFields.length === 0 }"
            >&#xe91c;</div>
            <div
              class="c-down-btn c-btn"
              v-on:click="isLastSortColField || sortColFields.length === 0 ? null : sortColFieldDown()"
              v-bind:class="{ 'c-inactive': isLastSortColField || sortColFields.length === 0 }"
            >&#xe91b;</div>
          </div>
          <div 
            class="c-settings-list"
            @dragover.prevent
            @drop.prevent="sortColFieldDropOnList"
          >
            <transition-group type="transition" name="c-settings-list" tag="div">
              <div
                v-for="colField in sortColFields"
                :key="colField.dataFieldIdent"
                draggable="true"
                :class="['c-settings-list-item', { 'c-active': colField === currentSortColField }]"
                @click="onClickSortColField($event, colField)"
                @dragstart="sortColFieldDragStart($event, colField)"
                @dragend="sortColFieldDragEnd"
                @drop.prevent.stop="sortColFieldDrop($event, colField)"
              >
                <div>{{ colField.dataFieldColTranslatedDesc }}</div>
                <div
                  class="c-btn c-sorting-button"
                  v-if="colField.isDesc === 0"
                  @click="setSortColFieldDesc($event, colField)"
                >&#xe91c;</div>
                <div
                  class="c-btn c-sorting-button"
                  v-else
                  @click="setSortColFieldAsc($event, colField)"
                >&#xe91b;</div>
              </div>
            </transition-group>
          </div>
        </div>
      </div>
      <div class="c-settings-layout-area" v-if="settingsTabSelected === 3">
        <div class="c-settings-cols">
          <div>
            <div>Kolumny</div>
          </div>
          <div class="c-settings-list">
            <div
              v-for="colField in colFields"
              :key="colField.dataFieldIdent"
              :class="['c-settings-list-item', { 'c-active': colField === currentColField }]"
              @click="onClickColField($event, colField)"
            >
              <div>{{ colField.dataFieldColTranslatedDesc }}</div>
              <div style="margin-left: auto;">{{getColFieldAggrTypeActive(colField)}}</div>
            </div>
          </div>
        </div>
        <div class="c-settings-actions-vertical">
        </div>
        <div class="c-settings-sortings">
          <div>
            <div>Agregaty</div>
          </div>
          <div class="c-settings-list">
            <div
              v-for="aggrType in aggrTypes"
              :key="aggrType"
              :class="['c-settings-list-item', { 'c-active': aggrType === getCurrentAggrType }]"
              @click="currentAggrType = aggrType"
            >
              <input
                type="checkbox"
                :id="aggrType"
                :checked="isCurrentColFieldAggrChecked(aggrType)"
                @change="toggleCurrentColFieldAggr($event, aggrType)"
              />
              <label class="c-checkbox" :for="aggrType" />
              <div>{{aggrType}}</div>
            </div>
          </div>
        </div>
      </div>
      <div class="c-settings-exports-area" v-if="settingsTabSelected === 4">
        <div class="c-settings-export">
          <c-btna
            style="width: 180px;"
            :appWindowIdent="appWindowIdent"
            :dataSetIdent="dataSetIdent"
            actionIdent="exportXLSX"
          />
        </div>
      </div>
      <div class="c-settings-footer">
        <div class="c-settings-btn-refresh c-btna ManageU" v-on:click="clear">Wyczyść</div>
        <div class="c-settings-btn-refresh c-btna ManageI" v-on:click="refresh">Odśwież</div>
        <div class="c-settings-btn-refresh c-btna ManageD" v-on:click="settingsVisibleChange">Zamknij</div>
      </div>
    </div>
    <div
      class="c-header"
      v-if="showHeaders"
    >
      <div
        v-if="showRowCheck || additionalInfo"
        class="c-settings"
        :style="{ width: rowsHeadersWidth  + 'px' }"
      >
        <div v-if="showRowCheck" :style="{'width': rowHeaderDefWidth + 'px', 'margin-left': rowsHeadersWidth - rowHeaderDefWidth + 'px'}">
          <input type="checkbox" v-on:change="onSelectedRowHeaderValueChange" :id="componentId" />
          <label class="c-checkbox" :for="componentId" />
        </div>
      </div>
      <div
        class="c-cols-headers"
        :style="{
          'padding-right': (rowsScrollBarWidth > 0 ? rowsScrollBarWidth + 1 : 0) + 'px',
          width: `calc(100% - ${rowsHeadersWidth}px)`
        }"
      >
        <div v-show="visibleColFieldsLockedLeft.length > 0" class="c-cols-headers-left">
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedLeft"
                :key="colField.dataFieldIdent"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <thead>
              <tr v-if="anyVisibleColFieldsHasGroup" class="c-cols-headers-row-groups">
                <th
                  v-for="({groupName, colspan}, i) in visibleColFieldsLockedLeftGroupsInOrder"
                  :key="i"
                  :colspan="colspan"
                >
                  <div class="c-header-container">
                    <div>{{groupName}}</div>
                  </div>
                </th>
              </tr>
              <draggable 
                class="c-cols-headers-row c-locks-left"
                data-usevisible="true"
                tag="tr"
                v-bind="dragOptions"
                @start="onDragStartColFieldLockedLeft"
                @end="onDragEndColFieldLockedLeft"
              >
                <th
                  v-for="(colField, i) in visibleColFieldsLockedLeft"
                  :key="colField.dataFieldIdent"
                  @click.exact="colFieldClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.shift="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.ctrl="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  :class="[
                    {
                      'c-first-header': i === 0, 
                      'c-last-header': i === visibleColFieldsLockedLeft.length - 1
                    }, 
                    (colField.headerSlotName != null ? 'c-slot-' + colField.headerSlotName : null)
                  ]"
                >
                  <div class="c-header-container">
                    <slot
                      v-if="colField.headerSlotName"
                      :name="colField.headerSlotName"
                      v-bind:value="colField"
                    >
                      Missing slot
                      <code>{{ colField.headerSlotName }}</code>
                    </slot>
                    <div v-else>{{ colField.dataFieldColTranslatedDesc }}</div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 0"
                    >
                      <div>&#xe91e;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 1"
                    >
                      <div>&#xe91d;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                  </div>
                  <div
                    class="dragger"
                    :key="i"
                    @mousedown.prevent="resizeHeaderMouseDown($event, i)"
                    @click.stop
                    :style="{ height: colFieldsMaxHeight + 'px' }"
                  />
                </th>
              </draggable>
            </thead>
          </table>
        </div>
        <div class="c-cols-headers-default" ref="scrolledLeft">
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedDefault"
                :key="colField.dataFieldIdent"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <thead>
              <tr v-if="anyVisibleColFieldsHasGroup" class="c-cols-headers-row-groups">
                <th
                  v-for="({groupName, colspan}, i) in visibleColFieldsLockedDefaultGroupsInOrder"
                  :key="i"
                  :colspan="colspan"
                >
                  <div class="c-header-container">
                    <div>{{groupName}}</div>
                  </div>
                </th>
              </tr>
              <draggable 
                class="c-cols-headers-row c-locks-default"
                data-usevisible="true"
                tag="tr"
                v-bind="dragOptions"
                @start="onDragStartColFieldLockedDefault"
                @end="onDragEndColFieldLockedDefault"
              >
                <th
                  v-for="(colField, i) in visibleColFieldsLockedDefault"
                  :key="colField.dataFieldIdent"
                  @click.exact="colFieldClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.shift="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.ctrl="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  :class="[
                    {
                      'c-first-header': i === 0,
                      'c-last-header': i === visibleColFieldsLockedDefault.length - 1
                    },
                    (colField.headerSlotName != null ? 'c-slot-' + colField.headerSlotName : null)
                  ]"
                >
                  <div class="c-header-container">
                    <slot
                      v-if="colField.headerSlotName"
                      :name="colField.headerSlotName"
                      v-bind:value="colField"
                    >
                      Missing slot
                      <code>{{ colField.headerSlotName }}</code>
                    </slot>
                    <div v-else>{{ colField.dataFieldColTranslatedDesc }}</div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 0"
                    >
                      <div>&#xe91e;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 1"
                    >
                      <div>&#xe91d;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                  </div>
                  <div
                    class="dragger"
                    :key="i"
                    @mousedown.prevent="resizeHeaderMouseDown($event, i)"
                    @click.stop
                    :style="{ height: colFieldsMaxHeight + 'px' }"
                  />
                </th>
              </draggable>
            </thead>
          </table>
        </div>
        <div v-show="visibleColFieldsLockedRight.length > 0" class="c-cols-headers-right">
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedRight"
                :key="colField.dataFieldIdent"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <thead>
              <tr v-if="anyVisibleColFieldsHasGroup" class="c-cols-headers-row-groups">
                <th
                  v-for="({groupName, colspan}, i) in visibleColFieldsLockedRightGroupsInOrder"
                  :key="i"
                  :colspan="colspan"
                >
                  <div class="c-header-container">
                    <div>{{groupName}}</div>
                  </div>
                </th>
              </tr>
              <draggable 
                class="c-cols-headers-row c-locks-right"
                data-usevisible="true"
                tag="tr"
                v-bind="dragOptions"
                @start="onDragStartColFieldLockedRight"
                @end="onDragEndColFieldLockedRight"
              >
                <th
                  v-for="(colField, i) in visibleColFieldsLockedRight"
                  :key="colField.dataFieldIdent"
                  @click.exact="colFieldClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.shift="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  @click.ctrl="colFieldShiftClick($event, colField, getSortColField(colField.dataFieldIdent))"
                  :class="[
                    {
                      'c-first-header': i === 0, 
                      'c-last-header': i === visibleColFieldsLockedRight.length - 1
                    }, 
                    (colField.headerSlotName != null ? 'c-slot-' + colField.headerSlotName : null)
                  ]"
                  :style="{
                    'padding-right': i === visibleColFieldsLockedRight.length - 1 && getShowSettings ? '15px': ''
                  }"
                >
                  <div class="c-header-container">
                    <slot
                      v-if="colField.headerSlotName"
                      :name="colField.headerSlotName"
                      v-bind:value="colField"
                    >
                      Missing slot
                      <code>{{ colField.headerSlotName }}</code>
                    </slot>
                    <div v-else>{{ colField.dataFieldColTranslatedDesc }}</div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 0"
                    >
                      <div>&#xe91e;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                    <div
                      class="c-column-sorting"
                      v-if="getSortColFieldIsDesc(colField.dataFieldIdent) === 1"
                    >
                      <div>&#xe91d;</div>
                      {{ getSortColFieldOrd(colField.dataFieldIdent) }}
                    </div>
                  </div>
                  <div
                    class="dragger"
                    :key="i"
                    @mousedown.prevent="resizeHeaderMouseDown($event, i)"
                    @click.stop
                    :style="{ height: colFieldsMaxHeight + 'px' }"
                  />
                </th>
              <!--<th class="c-top-right-dz"></th>-->
              </draggable>
            </thead>
          </table>
        </div>
      </div>
      <button
        v-if="getShowSettings"
        class="c-btn-settings"
        type="button"
        tabindex="-1"
        v-on:click.stop="settingsVisibleChange"
      ><div></div></button>
    </div>
    <div class="c-rows" v-if="state === 1 && !rowsIsEmpty">
      <div
        class="c-rows-headers"
        v-if="showRowCheck || additionalInfo"
        ref="scrolledTop"
        :style="{width: rowsHeadersWidth + 'px','min-width': rowsHeadersWidth + 'px'}"
      >
        <table cellspacing="0">
          <tbody>
            <template v-for="(row, rowIndex) in rows">
              <tr
                :key="rowIndex"
                :class="{'c-additional-info-exp': additionalInfo && row._showAdditionalInfo === 1, 'c-active': row === currentRow }"
                v-on:click="onClickRow(row)"
              >
                <td
                  v-if="additionalInfo"
                  class="c-show-additional-info"
                  :style="{ width: rowHeaderDefWidth + 'px', height: rowColFieldsMaxHeight + 'px' }"
                >
                  <button
                    class="c-additional-info-btn"
                    :class="{'c-show': row._showAdditionalInfo === 1}"
                    @click="showAdditionalInfo($event, row)"
                  >
                  </button>
                </td>
                <td
                  v-if="showRowCheck"
                  v-bind:class="['c-select-row', { 'c-active': row === currentRow }]"
                  :style="{ width: rowHeaderDefWidth + 'px', height: rowColFieldsMaxHeight + 'px' }"
                >
                  <c-rowcheck
                    :appWindowIdent="appWindowIdent"
                    :dataSetIdent="dataSetIdent"
                    :rowIndex="rowIndex"
                    :row="row"
                  ></c-rowcheck>
                </td>
              </tr>
              <tr
                v-if="additionalInfo && row && row._showAdditionalInfo === 1 && $scopedSlots.additionalInfo"
                :key="rowIndex + 'addInfo'"
                class="c-additional-info"
                :style="{height: row._additionalInfoHeight + 'px' }"
              >
                <td/>
              </tr>
            </template>
            <tr class="c-bootom-left-dz"></tr>
          </tbody>
        </table>
      </div>
      <div class="c-rows-data" v-if="state === 1 && !rowsIsEmpty">
        <div
          v-if="visibleColFieldsLockedLeft.length > 0"
          class="c-rows-data-background-left"
          X:style="{
            'padding-top': virtDataTop + 'px',
            'min-width': virtDataLockedLeftWidth + 'px',
            'min-height': virtDataHeight + 'px',
            'margin-bottom': (rowsScrollBarHeight + (hasAggrFields4Display ? aggrsDefHeight : 0)) + 'px',
            left: 0
          }"
          @scroll="handleScrollTop"
          ref="rowsDataLockedLeft"
        >
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedLeft"
                :key="colField.key"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <tbody>
              <template v-for="(row, rowIndex) in virtRowsCount">
                <tr
                  :key="rowIndex"
                  :style="{ height: rowColFieldsMaxHeight + 'px' }"
                  :class="{ 
                    'c-additional-info-exp': additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1, 'c-active': rows[rowShift + rowIndex] == currentRow 
                  }"
                  v-contextmenu:contextMenu
                >
                  <td
                    v-for="colField in visibleColFieldsLockedLeft"
                    :key="colField.key"
                    :class="[
                      { 'c-active': rows[rowShift + rowIndex] == currentRow },
                      getFormatTypeClass(colField.formatType),
                      (colField.slotName != null ? 'c-slot-' + colField.slotName : null)
                    ]"
                    @click="onClickRow(rows[rowShift + rowIndex])"
                    @dblclick="onDblClickRow(rows[rowShift + rowIndex])"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                    :style= "{
                      'text-align': colField.slotName == null ? ['numeric', 'integer', 'money', 'decimal'].includes(colField.formatType) ? 'right' : 'left' : ''
                    }"
                  >
                    <slot
                      v-if="colField.slotName"
                      :name="colField.slotName"
                      :row="rows[rowShift + rowIndex]"
                    />
                    <template v-else-if="colField.formatType === 'boolean'" >
                      <input 
                        type="checkbox" 
                        :id="colField.dataFieldIdent" 
                        :checked="rows[rowShift + rowIndex][colField.dataFieldIdent]"
                        :disabled=true
                      />
                      <label
                        :for="colField.dataFieldIdent"
                        class="c-checkbox"
                        style="cursor:default"
                      ></label>
                    </template>
                    <template v-else>
                      {{formatValue(rows[rowShift + rowIndex][colField.dataFieldIdent],colField.formatType)}}
                    </template>
                  </td>
                </tr>
                <tr
                  v-if="additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1 && $scopedSlots.additionalInfo"
                  :key="rowIndex + 'addInfo'"
                  class="c-additional-info"
                  v-contextmenu:contextMenu
                >
                  <td 
                    :colspan="visibleColFieldsLockedLeft.length"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                  >
                    <div></div>
                  </td>
                </tr>
              </template>
            </tbody>
          </table>
        </div>
        <div
          class="c-rows-data-background c-rows-data-background-default"
          X:style="[{
            'padding-top': virtDataTop + 'px',
            'padding-left': (virtDataLeft + visibleColsLockedLeftWidth) + 'px',
            'padding-right': visibleColsLockedRightWidth + 'px',
            'min-width': virtDataLockedDefaultWidth + 'px',
            'min-height': virtDataHeight + 'px',
          }, visibleColFieldsLockedRight.length === 0 ? 'overflow-y:auto;' : '']"
          @scroll="handleScroll"
          ref="rowsDataLockedDefault"
        >
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedDefault"
                :key="colField.key"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <tbody>
              <template v-for="(row, rowIndex) in virtRowsCount">
                <tr
                  :key="rowIndex"
                  :style="{ height: rowColFieldsMaxHeight + 'px' }"
                  :class="{
                    'c-additional-info-exp': additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1, 
                    'c-active': rows[rowShift + rowIndex] == currentRow
                  }"
                  v-contextmenu:contextMenu
                >
                  <td
                    v-for="colField in visibleColFieldsLockedDefault"
                    :key="colField.key"
                    :class="[
                      { 'c-active': rows[rowShift + rowIndex] == currentRow },
                      getFormatTypeClass(colField.formatType),
                      (colField.slotName != null ? 'c-slot-' + colField.slotName : null)
                    ]"
                    @click="onClickRow(rows[rowShift + rowIndex])"
                    @dblclick="onDblClickRow(rows[rowShift + rowIndex])"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                    :style= "{
                      'text-align': colField.slotName == null ? ['numeric', 'integer', 'money', 'decimal'].includes(colField.formatType) ? 'right' : 'left' : ''
                    }"
                  >
                    <slot
                      v-if="colField.slotName"
                      :name="colField.slotName"
                      :row="rows[rowShift + rowIndex]"
                    />
                    <template v-else-if="colField.formatType === 'boolean'" >
                      <input 
                        type="checkbox" 
                        :id="colField.dataFieldIdent" 
                        :checked="rows[rowShift + rowIndex][colField.dataFieldIdent]"
                        :disabled=true
                      />
                      <label
                        :for="colField.dataFieldIdent"
                        class="c-checkbox"
                        style="cursor:default"
                      ></label>
                    </template>
                    <template v-else>
                      {{formatValue(rows[rowShift + rowIndex][colField.dataFieldIdent],colField.formatType)}}
                    </template>
                  </td>
                </tr>
                <tr
                  v-if="additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1 && $scopedSlots.additionalInfo"
                  :key="rowIndex + 'addInfo'"
                  class="c-additional-info"
                  v-contextmenu:contextMenu
                >
                  <td 
                    :colspan="visibleColFieldsLockedDefault.length"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                  >
                    <div :style="{ 'margin-left': -visibleColsLockedLeftWidth + 'px' }">
                      <slot
                        name="additionalInfo"
                        :row="rows[rowShift + rowIndex]"
                      />
                    </div>
                  </td>
                </tr>
              </template>
            </tbody>
          </table>
        </div>
        <div
          v-if="visibleColFieldsLockedRight.length > 0"
          class="c-rows-data-background-right"
          X:style="{
            'padding-top': virtDataTop + 'px',
            'min-width': virtDataLockedRightWidth + 'px',
            'min-height': virtDataHeight + 'px',
            'margin-bottom': (rowsScrollBarHeight + (hasAggrFields4Display ? aggrsDefHeight : 0)) + 'px',
            right: 0
          }"
          @scroll="handleScrollTop"
          ref="rowsDataLockedRight"
        >
          <table cellspacing="0">
            <colgroup>
              <col
                v-for="colField in visibleColFieldsLockedRight"
                :key="colField.key"
                :style="{ width: colField.width + 'px' }"
              />
            </colgroup>
            <tbody>
              <template v-for="(row, rowIndex) in virtRowsCount">
                <tr
                  :key="rowIndex"
                  :style="{ height: rowColFieldsMaxHeight + 'px' }"
                  :class="{
                    'c-additional-info-exp': additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1, 
                    'c-active': rows[rowShift + rowIndex] == currentRow
                  }"
                  v-contextmenu:contextMenu
                >
                  <td
                    v-for="colField in visibleColFieldsLockedRight"
                    :key="colField.key"
                    :class="[
                      { 'c-active': rows[rowShift + rowIndex] == currentRow },
                      getFormatTypeClass(colField.formatType),
                      (colField.slotName != null ? 'c-slot-' + colField.slotName : null)
                    ]"
                    @click="onClickRow(rows[rowShift + rowIndex])"
                    @dblclick="onDblClickRow(rows[rowShift + rowIndex])"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                    :style= "{
                      'text-align': colField.slotName == null ? ['numeric', 'integer', 'money', 'decimal'].includes(colField.formatType) ? 'right' : 'left' : ''
                    }"
                  >
                    <slot
                      v-if="colField.slotName"
                      :name="colField.slotName"
                      :row="rows[rowShift + rowIndex]"
                    />
                    <template v-else-if="colField.formatType === 'boolean'" >
                      <input 
                        type="checkbox" 
                        :id="colField.dataFieldIdent" 
                        :checked="rows[rowShift + rowIndex][colField.dataFieldIdent]"
                        :disabled=true
                      />
                      <label
                        :for="colField.dataFieldIdent"
                        class="c-checkbox"
                        style="cursor:default"
                      ></label>
                    </template>
                    <template v-else>
                      {{formatValue(rows[rowShift + rowIndex][colField.dataFieldIdent],colField.formatType)}}
                    </template>
                  </td>
                </tr>
                <tr
                  v-if="additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1 && $scopedSlots.additionalInfo"
                  :key="rowIndex + 'addInfo'"
                  class="c-additional-info"
                  v-contextmenu:contextMenu
                >
                  <td 
                    :colspan="visibleColFieldsLockedRight.length"
                    @click.right="onClickRow(rows[rowShift + rowIndex])"
                  >
                    <div></div>
                  </td>
                </tr>
              </template>
            </tbody>
          </table>
        </div>
      </div>
      <div
        class="c-rows-footers"
        v-if="rowFooterAction"
        ref="scrolledTop"
        :style="{width: 0 + 'px','min-width': 0 + 'px'}"
      >
        <table cellspacing="0">
          <tbody>
            <tr
              v-for="(row, rowIndex) in rows" :key="row.key"
              :class="{
                'c-additional-info-exp': additionalInfo && rows[rowShift + rowIndex]._showAdditionalInfo === 1, 
                'c-active': rows[rowShift + rowIndex] == currentRow
              }"
            >
              <td
                v-bind:class="['c-select-row', { 'c-active': row === currentRow }]"
                :style="{ width: 23 + 'px', height: rowColFieldsMaxHeight + 'px' }"
              >
                <c-btna
                  class="c-btn-row-footer-action"
                  :appWindowIdent="appWindowIdent"
                  :dataSetIdent="dataSetIdent"
                  :action-ident="rowFooterAction"
                  source-kind="rows"
                  :row="row"
                  :showLabel="false"
                ></c-btna>
              </td>
            </tr>
            <tr class="c-bootom-left-dz"></tr>
          </tbody>
        </table>
      </div>
    </div>
    <div
      class="c-aggrs"
      v-if="state === 1 && !rowsIsEmpty && hasAggrFields4Display"
      :Xstyle="{ 
        height: aggrsDefHeight + 'px', 
        'margin-top': -aggrsDefHeight - rowsScrollBarHeight + 'px', 
        'margin-right': (rowsScrollBarWidth > 0 ? rowsScrollBarWidth+1 : 0) + 'px', 
        'margin-bottom': rowsScrollBarHeight + 'px',
        'margin-left': (showRowCheck || additionalInfo ? rowsHeadersWidth : 0) + 'px'
      }"
    >
      <div v-if="visibleColFieldsLockedLeft.length > 0" class="c-aggrs-left">
        <table cellspacing="0">
          <colgroup>
            <col
              v-for="colField in visibleColFieldsLockedLeft"
              :key="colField.key"
              :style="{ width: colField.width + 'px'}"
            />
          </colgroup>
          <tfoot class="c-aggrs-footer">
            <tr
              :style="{ height: aggrsDefHeight + 'px' }"
            >
              <td
                v-for="colField in visibleColFieldsLockedLeft"
                :key="colField.key"
                :class="[
                  { 'c-aggr': getAggrField(colField.dataFieldIdent) != null },
                  getAggrField(colField.dataFieldIdent) != null ? getFormatTypeClass(colField.formatType) : null
                ]"
              >
                <template v-if="getAggrField(colField.dataFieldIdent) != null" >
                  <div>
                    <span>{{ getAggrField(colField.dataFieldIdent).aggrTranslatedDesc }}</span>
                    <span>{{ formatValue(aggregates[colField.dataFieldIdent], colField.formatType) }}</span>
                  </div>
                </template>
              </td>
              <!--<th class="c-top-right-dz"></th>-->
            </tr>
          </tfoot>
        </table>
      </div>
      <div class="c-aggrs-default" ref="aggrs">
        <table cellspacing="0">
          <colgroup>
            <col
              v-for="colField in visibleColFieldsLockedDefault"
              :key="colField.key"
              :style="{ width: colField.width + 'px'}"
            />
          </colgroup>
          <tfoot class="c-aggrs-footer">
            <tr
              :style="{ height: aggrsDefHeight + 'px' }"
            >
              <td
                v-for="colField in visibleColFieldsLockedDefault"
                :key="colField.key"
                :class="[
                  { 'c-aggr': getAggrField(colField.dataFieldIdent) != null },
                  getAggrField(colField.dataFieldIdent) != null ? getFormatTypeClass(colField.formatType) : null
                ]"
              >
                <template v-if="getAggrField(colField.dataFieldIdent) != null" >
                  <div>
                    <span>{{ getAggrField(colField.dataFieldIdent).aggrTranslatedDesc }}</span>
                    <span>{{ formatValue(aggregates[colField.dataFieldIdent], colField.formatType) }}</span>
                  </div>
                </template>
              </td>
              <!--<th class="c-top-right-dz"></th>-->
            </tr>
          </tfoot>
        </table>
      </div>
      <div v-if="visibleColFieldsLockedRight.length > 0" class="c-aggrs-right">
        <table cellspacing="0">
          <colgroup>
            <col
              v-for="colField in visibleColFieldsLockedRight"
              :key="colField.key"
              :style="{ width: colField.width + 'px'}"
            />
          </colgroup>
          <tfoot class="c-aggrs-footer">
            <tr
              :style="{ height: aggrsDefHeight + 'px' }"
            >
              <td
                v-for="colField in visibleColFieldsLockedRight"
                :key="colField.key"
                :class="[
                  { 'c-aggr': getAggrField(colField.dataFieldIdent) != null },
                  getAggrField(colField.dataFieldIdent) != null ? getFormatTypeClass(colField.formatType) : null
                ]"
              >
                <template v-if="getAggrField(colField.dataFieldIdent) != null" >
                  <div>
                    <span>{{ getAggrField(colField.dataFieldIdent).aggrTranslatedDesc }}</span>
                    <span>{{ formatValue(aggregates[colField.dataFieldIdent], colField.formatType) }}</span>
                  </div>
                </template>
              </td>
              <!--<th class="c-top-right-dz"></th>-->
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
    <div v-if="state === 0 && showDataProgress" class="c-progress">
      <slot v-if="$scopedSlots.progress" name="progress"></slot>
      <template v-else>
        <c-data-progress></c-data-progress>
      </template>
    </div>
    <div v-if="state === -1" class="c-errors">
      <slot v-if="$scopedSlots.errors" name="errors"></slot>
      <template v-else>
        <c-data-errors></c-data-errors>
      </template>
    </div>
    <div v-if="state === 1 && rowsIsEmpty && showDataEmpty" class="c-empty">
      <slot v-if="$scopedSlots.empty" name="empty"></slot>
      <template v-else>
        <c-data-empty></c-data-empty>
      </template>
    </div>
    <div class="c-status-bar" v-if="(state === 1 || state === 0) && !rowsIsEmpty && showStatusBar">
      <div class="c-settings" v-if="getShowSettings" :style="{ width: settingsWidth + 'px' }">
        <div class="c-settings-btn" v-on:click="settingsVisibleChange">&#xe913;</div>
      </div>
      <a
        v-if="showFullScreen"
        class="c-new-tab"
        target="_blank"
        title="Otwórz w nowym oknie"
        :href="getFullPathHref"
        X:style="{ width: rowsHeadersWidth + 'px' }"
      >&#xe989;</a>
      <c-layouts-manager
        v-if="getShowLayoutsManager"
        :appWindowIdent="appWindowIdent"
        :dataSetIdent="dataSetIdent"
      />
      <c-pager
        v-if="showPager"
        class="c-pager-rows"
        :appWindowIdent="appWindowIdent"
        :dataSetIdent="dataSetIdent"
        :kind="pagerSettings ? pagerSettings.kind : 'determinate'"
        :sourceKind="pagerSettings ? pagerSettings.sourceKind : 'rows'"
        :labelCount="pagerSettings ? pagerSettings.labelCount : 'wierszy'"
        :btnsCnt="pagerSettings ? pagerSettings.btnsCnt : undefined"
        :showFirstPageButton="pagerSettings ? pagerSettings.showFirstPageButton : undefined"
        :showLastPageButton="pagerSettings ? pagerSettings.showLastPageButton : undefined"
        :showPreviousPageButton="pagerSettings ? pagerSettings.showPreviousPageButton : undefined"
        :showNextPageButton="pagerSettings ? pagerSettings.showNextPageButton : undefined"
        :previousPageButtonLabel="pagerSettings ? pagerSettings.previousPageButtonLabel : undefined"
        :nextPageButtonLabel="pagerSettings ? pagerSettings.nextPageButtonLabel : undefined"
        :showPagesCnt="pagerSettings ? pagerSettings.showPagesCnt : undefined"
        :showFirstPage="pagerSettings ? pagerSettings.showFirstPage : undefined"
        :scrollTopOnPageChange="pagerSettings ? pagerSettings.scrollTopOnPageChange : undefined"
      />
    </div>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex"
import controlUtils from "../classes/controlUtils"
import base from "./c-base"
import cBtna from './c-btna'
import cRowcheck from './c-rowcheck'
import cPager from './c-pager'
import cDataProgress from './c-data-progress'
import cDataErrors from './c-data-errors'
import cDataEmpty from './c-data-empty'
import cLayoutsManager from './c-layouts-manager'
import Vue from 'vue'
import vuescroll from 'vue-scroll'
import draggable from 'vuedraggable'

Vue.use(vuescroll)

export default {
  extends: base,
  components: {
    'c-btna': cBtna,
    'c-rowcheck': cRowcheck,
    'c-pager': cPager,
    'c-data-progress': cDataProgress,
    'c-data-errors': cDataErrors,
    'c-data-empty': cDataEmpty,
    'c-layouts-manager': cLayoutsManager,
    draggable
  },
  props: {
    showDataProgress: {
      type: Boolean,
      default: true
    },
    showDataEmpty: {
      type: Boolean,
      default: true
    },
    showSettings: {
      type: Boolean,
      default: null
    },
    showRowCheck: {
      type: Boolean,
      default: true
    },
    showFullScreen:{
      type: Boolean,
      default: true
    },
    showStatusBar:{
      type: Boolean,
      default: true
    },
    showPager:{
      type: Boolean,
      default: true
    },
    showLayoutsManager:{
      type: Boolean,
      default: null
    },
    pagerSettings:{
      type: Object,
      default: null
    },
    showHeaders:{
      type: Boolean,
      default: true
    },
    defaultLayoutIdent:{
      type: String,
      default: null
    },
    rowFooterAction:{
      type: String,
      default: null
    },
    useVirtualization: {
      type: Boolean,
      default: false
    },
    additionalInfo: {
      type: Boolean,
      default: false
    },
    changePageOnScroll: {
      type: Boolean,
      default: false
    },
    showOneAdditionalInfoAtATime: {
      type: Boolean,
      default: false
    }
  },
  data: function() {
    return {
      componentClass: "c-grid",
      settingsVisible: false,
      scrollTop: 0,
      scrollLeft: 0,
      rowColFieldsMaxHeight: 26,
      colFieldsMaxHeight: 30,
      selectedRow: [],
      resizingColumnIndex: -1,
      draggingColField: null,
      draggingSortColField: null,
      draggingColFieldLockedLeft: null,
      draggingColFieldLockedRight: null,
      settingsTabSelected: 1,
      rowHeaderDefWidth: 35,
      aggrsDefHeight: 25,
      rowsScrollBarWidth: 0,
      rowsScrollBarHeight: 0,
      rowsScrollBarHeightPx: null,
      rowsScrollBarWidthPx: null,
      currentAggrType: 'SUM',
      contextMenu: null
    };
  },
  created: function() {
    this.rowColFieldsMaxHeight = this.getDataSetRowColFieldsMaxHeight(this.dataSet);
    this.colFieldsMaxHeight = this.getDataSetColFieldsMaxHeight(this.dataSet);
    if (this.defaultLayoutIdent)
      this.setDataSetLayoutIdent({
        dataSet: this.dataSet,
        layoutIdent: this.defaultLayoutIdent
      })
  },
  mounted: function() {
    this.contextMenu = this.$refs.contextMenu
    //
    this.$nextTick(() => {
      this.clientHeight = this.$el.clientHeight;
      this.clientWidth = this.$el.clientWidth;
    });
    // window.addEventListener("resize", this.handleResize);
    this.rowsScrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault) - 1
    this.rowsScrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault) - 1
    //
    let scrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault)
    this.rowsScrollBarWidthPx = scrollBarWidth != null ? scrollBarWidth + 'px' : null

    let scrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault)
    this.rowsScrollBarHeightPx = scrollBarHeight != null ? scrollBarHeight + 'px' : null
    //
    this.setCurrentColField({ dataSet: this.dataSet })
    this.setCurrentColFieldLockedLeft({ dataSet: this.dataSet })
    this.setCurrentColFieldLockedRight({ dataSet: this.dataSet })
  },
  updated: function(){
    this.rowsScrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault) - 1
    this.rowsScrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault) - 1
    //
    let scrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault)
    this.rowsScrollBarWidthPx = scrollBarWidth != null ? scrollBarWidth + 'px' : null

    let scrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault)
    this.rowsScrollBarHeightPx = scrollBarHeight != null ? scrollBarHeight + 'px' : null
  },
  // beforeDestroy: function() {
  //   window.removeEventListener("resize", this.handleResize);
  // },
  watch: {
    state: function() {
      this.resetScrolls();
    },
    scrollTop: function(val, oldVal) {
      let o = this.$refs.scrolledTop;
      let rowsDataLockedLeft = this.$refs.rowsDataLockedLeft;
      let rowsDataLockedDefault = this.$refs.rowsDataLockedDefault;
      let rowsDataLockedRight = this.$refs.rowsDataLockedRight;
      if(!o && !rowsDataLockedLeft && !rowsDataLockedRight)
        return
      if (!this.changePageOnScroll){
        this.$nextTick(() => {
          this.clientHeight = o.clientHeight
          o.scrollTop = val

          if (rowsDataLockedLeft) rowsDataLockedLeft.scrollTop = val
          rowsDataLockedDefault.scrollTop = val
          if (rowsDataLockedRight) rowsDataLockedRight.scrollTop = val
        })
        return
      }
      let goPageNoPrev = o.scrollTop === 0 && val < oldVal;
      let goPageNoNext =
        o.scrollHeight - o.offsetHeight - val < 10 &&
        val > oldVal &&
        this.pageNo < this.pagesCount;
      this.$nextTick(() => {
        if (!goPageNoNext && !goPageNoPrev) {
          this.clientHeight = o.clientHeight
          o.scrollTop = val

          if (rowsDataLockedLeft) rowsDataLockedLeft.scrollTop = val
          rowsDataLockedDefault.scrollTop = val
          if (rowsDataLockedRight) rowsDataLockedRight.scrollTop = val
        }
        if (goPageNoNext) {
          let payloadPageOperation = {
            appWindowIdent: this.appWindowIdent,
            dataSet: this.dataSet
          };
          this.setDataSetPageNoNext(payloadPageOperation);
        }
        if (goPageNoPrev) {
          let payloadPageOperation = {
            appWindowIdent: this.appWindowIdent,
            dataSet: this.dataSet
          };
          if (this.pageNo > 1) {
            this.setDataSetPageNoPrev(payloadPageOperation);
          }
        }
      });
    },
    scrollLeft: function(val) {
      let o = this.$refs.scrolledLeft
      let a = this.$refs.aggrs

      if(!o)
        return
      this.$nextTick(() => {
        this.clientWidth = o.clientWidth
        o.scrollLeft = val

        if (a) {
          a.scrollLeft = val
        }
      });
    },
    defaultLayoutIdent: function(val){
      if (!val || val === this.layoutIdent)
        return
      this.setDataSetLayoutIdent({
        dataSet: this.dataSet,
        layoutIdent: val
      })
    }
  },
  computed: {
    ...mapGetters("csAppWindowsUtils", [
      "getDataSetBusy",
      "getDataSetRows",
      "getFullPathHref",
      "getDataSetColFieldsMaxHeight",
      "getDataSetRowColFieldsMaxHeight",
      "getDataSetSortColFields",
      "getDataSetSortIdent",
      "getDataSetSort",
      "getCurrentColField",
      "getCurrentColFieldLockedLeft",
      "getCurrentColFieldLockedRight",
      "getCurrentSortColField",
      "getCurrentColFieldIndex",
      "getCurrentColFieldLockedLeftIndex",
      "getCurrentColFieldLockedRightIndex",
      "getCurrentSortColFieldIndex",
      "getCGridShowSettings",
      "getCGridShowLayoutsManager"
    ]),
    aggrTypes: function() {
      return this.currentColField?.formatType === 'string' ? ['COUNT', 'MIN', 'MAX'] : ['SUM', 'AVG', 'COUNT', 'MIN', 'MAX']
    },
    getCurrentAggrType: function() {
      if (this.currentColField?.formatType === 'string' && !['COUNT', 'MIN', 'MAX'].includes(this.currentAggrType))
        return 'COUNT'
      return this.currentAggrType
    },
    rowShift: function() {
      return this.useVirtualization ? Math.floor(this.scrollTop / this.rowColFieldsMaxHeight) : 0;
    },
    rowMinVisible: function() {
      return this.useVirtualization ? Math.floor(this.scrollTop / this.rowColFieldsMaxHeight) + 1 : 1;
    },
    rowMaxVisible: function() {
      let result = Math.ceil(
        (this.clientHeight + 78 + this.scrollTop) / this.rowColFieldsMaxHeight
      );
      return result <= this.rows.length && this.useVirtualization ? result : this.rows.length;
    },
    virtRowsCount: function() {
      return this.useVirtualization ? this.rowMaxVisible - this.rowMinVisible + 1 : this.rows.length
    },
    colShift: function() {
      return Math.floor(this.scrollLeft / this.rowsWidth);
    },
    virtColsCount: function() {
      let result = this.useVirtualization ? Math.ceil(this.clientWidth / this.rowsWidth) : this.visibleColFields.length
      return result <= this.visibleColFields.length
        ? result
        : this.visibleColFields.length;
    },
    colMinVisible: function() {
      return Math.floor(this.scrollLeft / this.rowsWidth) + 1;
    },
    colMaxVisible: function() {
      return Math.ceil((this.clientWidth + this.scrollLeft) / this.rowsWidth);
    },
    virtDataLockedDefaultWidth: function() {
      return this.visibleColFieldsLockedDefault.reduce((result, colField) => result + colField.width, 60)
    },
    virtDataLockedLeftWidth: function() {
      return this.visibleColFieldsLockedLeft.reduce((result, colField) => result + colField.width, 60)
    },
    virtDataLockedRightWidth: function() {
      return this.visibleColFieldsLockedRight.reduce((result, colField) => result + colField.width, 60)
    },
    virtDataHeight: function() {
      return this.rows.length * this.colFieldsMaxHeight + 78 + (this.hasAggrFields4Display ? (this.aggrsDefHeight + this.rowsScrollBarHeight) : 0);
    },
    virtDataTop: function() {
      return this.useVirtualization ? (this.rowMinVisible - 1) * this.rowColFieldsMaxHeight : 0
    },
    virtDataLeft: function() {
      return this.useVirtualization ? (this.colMinVisible - 1) * this.rowsWidth : 0
    },
    sortColFields: function() {
      return this.getDataSetSortColFields(this.dataSet);
    },
    dataSetSort: function() {
      return this.getDataSetSort(
        this.dataSet,
        this.getDataSetSortIdent(this.dataSet)
      );
    },
    currentColField: function() {
      return this.getCurrentColField(this.dataSet);
    },
    currentColFieldIndex: function() {
      return this.getCurrentColFieldIndex(this.dataSet);
    },
    currentColFieldLockedLeft: function() {
      return this.getCurrentColFieldLockedLeft(this.dataSet);
    },
    currentColFieldLockedLeftIndex: function() {
      return this.getCurrentColFieldLockedLeftIndex(this.dataSet);
    },
    currentColFieldLockedRight: function() {
      return this.getCurrentColFieldLockedRight(this.dataSet);
    },
    currentColFieldLockedRightIndex: function() {
      return this.getCurrentColFieldLockedRightIndex(this.dataSet);
    },
    currentSortColFieldIndex: function() {
      return this.getCurrentSortColFieldIndex(this.dataSet);
    },
    currentSortColField: function() {
      return this.getCurrentSortColField(this.dataSet);
    },
    isFirstColField: function() {
      return this.currentColFieldIndex === this.colFields.indexOf(this.colFieldsLockedDefault[0])
    },
    isFirstSortColField: function() {
      return this.currentSortColFieldIndex === 0
    },
    isLastColField: function() {
      return this.currentColFieldIndex === this.colFields.indexOf(this.colFieldsLockedDefault[this.colFieldsLockedDefault.length - 1])
    },
    isLastSortColField: function() {
      return this.currentSortColFieldIndex === this.sortColFields.length - 1
    },
    isFirstColFieldLockedLeft: function () {
      return this.currentColFieldLockedLeftIndex === this.colFields.indexOf(this.colFieldsLockedLeft[0])
    },
    isLastColFieldLockedLeft: function () {
      return this.currentColFieldLockedLeftIndex === this.colFields.indexOf(this.colFieldsLockedLeft[this.colFieldsLockedLeft.length - 1])
    },
    isFirstColFieldLockedRight: function () {
      return this.currentColFieldLockedRightIndex === this.colFields.indexOf(this.colFieldsLockedRight[0])
    },
    isLastColFieldLockedRight: function () {
      return this.currentColFieldLockedRightIndex === this.colFields.indexOf(this.colFieldsLockedRight[this.colFieldsLockedRight.length - 1])
    },
    rowsHeadersWidth: function() {
      let result = this.showRowCheck ? this.rowHeaderDefWidth : 0
      result += this.additionalInfo ? this.rowHeaderDefWidth : 0
      return result
    },
    settingsWidth: function(){
      return this.rowsHeadersWidth ? this.rowsHeadersWidth : this.rowHeaderDefWidth
    },
    aggrFields4Display: function(){
      return this.aggrFields && this.aggrFields.length > 1 ? this.aggrFields.slice(1) : []
    },
    hasAggrFields4Display: function(){
      return this.aggrFields4Display.length > 0
    },
    colFieldsLockedDefault: function() {
      return this.colFields.filter(f => f.placement === 'default')
    },
    colFieldsLockedLeft: function() {
      return this.colFields.filter(f => f.placement === 'left')
    },
    colFieldsLockedRight: function() {
      return this.colFields.filter(f => f.placement === 'right')
    },
    visibleColFieldsLockedDefault: function() {
      return this.visibleColFields.filter(f => f.placement === 'default')
    },
    anyVisibleColFieldsHasGroup: function() {
      return this.visibleColFields.some(col => col.dataFieldColGroupTranslatedDesc != undefined)
    },
    visibleColFieldsLockedDefaultGroupsInOrder: function() {
      const result = []
      let colspan
      let prevGroup
      this.visibleColFieldsLockedDefault.forEach(col => {
        const group = col.dataFieldColGroupTranslatedDesc != undefined ? col.dataFieldColGroupTranslatedDesc : ''
        if (prevGroup === group) {
          colspan++
        } else {
          if (prevGroup != undefined) {
            result.push({
              groupName: prevGroup,
              colspan: colspan
            })
          }
          prevGroup = group
          colspan = 1
        }
      })

      result.push({
        groupName: prevGroup,
        colspan: colspan
      })

      return result;
    },
    visibleColFieldsLockedLeft: function() {
      return this.visibleColFields.filter(f => f.placement === 'left')
    },
    visibleColFieldsLockedLeftGroupsInOrder: function() {
      const result = []
      let colspan
      let prevGroup
      this.visibleColFieldsLockedLeft.forEach(col => {
        const group = col.dataFieldColGroupTranslatedDesc != undefined ? col.dataFieldColGroupTranslatedDesc : ''
        if (prevGroup === group) {
          colspan++
        } else {
          if (prevGroup != undefined) {
            result.push({
              groupName: prevGroup,
              colspan: colspan
            })
          }
          prevGroup = group
          colspan = 1
        }
      })

      result.push({
        groupName: prevGroup,
        colspan: colspan
      })

      return result;
    },
    visibleColFieldsLockedRight: function() {
      return this.visibleColFields.filter(f => f.placement === 'right')
    },
    visibleColFieldsLockedRightGroupsInOrder: function() {
      const result = []
      let colspan
      let prevGroup
      this.visibleColFieldsLockedRight.forEach(col => {
        const group = col.dataFieldColGroupTranslatedDesc != undefined ? col.dataFieldColGroupTranslatedDesc : ''
        if (prevGroup === group) {
          colspan++
        } else {
          if (prevGroup != undefined) {
            result.push({
              groupName: prevGroup,
              colspan: colspan
            })
          }
          prevGroup = group
          colspan = 1
        }
      })

      result.push({
        groupName: prevGroup,
        colspan: colspan
      })

      return result;
    },
    visibleColsLockedLeftWidth: function() {
      return this.visibleColFieldsLockedLeft.reduce((totalWidth, colField) => totalWidth + colField.width, 0)
    },
    visibleColsLockedRightWidth: function() {
      return this.visibleColFieldsLockedRight.reduce((totalWidth, colField) => totalWidth + colField.width, 0)
    },
    dragOptions: function() {
      return {
        animation: 200,
        group: "description",
        disabled: false,
        ghostClass: "ghost"
      }
    },
    getShowSettings: function() {
      return this.showSettings != null ? this.showSettings : this.getCGridShowSettings()
    },
    getShowLayoutsManager: function() {
      return this.showLayoutsManager != null ? this.showLayoutsManager : this.getCGridShowLayoutsManager()
    }
  },
  methods: {
    ...mapActions("csAppWindowsUtils", [
      "setDataSetPrevRow",
      "setDataSetNextRow",
      "setLookupDefSelection",
      "setDataSetPageNoNext",
      "setDataSetPageNoPrev",
      "setDataSetColFieldAttr",
      "setDataSetVisibleColFieldAttr",
      "setColFieldOrd",
      "setColFieldLockedLeftOrd",
      "setColFieldLockedRightOrd",
      "setColFieldVisibility",
      "addSortColFieldToSortIdent",
      "deleteSortColField",
      "setSortColFieldOrd",
      "setSortColFieldsIsDesc",
      "setCurrentColField",
      "setCurrentColFieldLockedLeft",
      "setCurrentColFieldLockedRight",
      "setCurrentSortColField",
      "deleteAllSortColFields",
      "setDataSetLayoutIdent",
      "deleteAllSelectedRow",
      "addAllSelectedRow",
      "toggleDataSetAggrField"
    ]),
    onSelectedRowHeaderValueChange: function(evt) {
      if (!evt.target.checked) {
        this.deleteAllSelectedRow({
          appWindowIdent: this.appWindowIdent,
          dataSetIdent: this.dataSetIdent
        })
      } else this.addAllSelectedRow({
        appWindowIdent: this.appWindowIdent,
        dataSetIdent: this.dataSetIdent
      })
    },
    handleScroll: function(evt) {
      this.scrollTop = evt.target.scrollTop;
      this.scrollLeft = evt.target.scrollLeft;
    },
    handleScrollTop: function(evt) {
      this.scrollTop = evt.target.scrollTop;
    },
    handleResize: function() {
      this.$nextTick(() => {
        this.clientHeight = this.$el.clientHeight;
        this.clientWidth = this.$el.clientWidth;
        this.rowsScrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault) - 1
        this.rowsScrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault) - 1
        //
        let scrollBarWidth = this.getScrollBarWidth(this.$refs.rowsDataLockedRight || this.$refs.rowsDataLockedDefault)
        this.rowsScrollBarWidthPx = scrollBarWidth != null ? scrollBarWidth + 'px' : null

        let scrollBarHeight = this.getScrollBarHeight(this.$refs.rowsDataLockedDefault)
        this.rowsScrollBarHeightPx = scrollBarHeight != null ? scrollBarHeight + 'px' : null
      });
    },
    settingsVisibleChange: function() {
      this.settingsVisible = this.settingsVisible ? false : true;
    },
    getFormatTypeClass: function(formatType) {
      return controlUtils.checkFormatType(formatType).formatTypeClass;
    },
    onClickRow: function(row) {
      this.setDataSetCurrentRow({ dataSet: this.dataSet, row: row });
    },
    onDblClickRow: async function(row) {
      await this.setDataSetCurrentRow({ dataSet: this.dataSet, row: row });
      await this.setLookupDefSelection({ appWindowIdent: this.appWindowIdent });
    },
    onKeyUp: function(evt) {
      if (evt.key === "ArrowDown") {
        this.setDataSetNextRow(this.dataSet);
      }
      if (evt.key === "ArrowUp") {
        this.setDataSetPrevRow(this.dataSet);
      }
      if (evt.key === "Enter") {
        this.setLookupDefSelection({ appWindowIdent: this.appWindowIdent });
      }
    },
    resetScrolls: function() {
      this.scrollTop = 0;
      this.scrollLeft = 0;
    },
    resizeHeaderMouseDown: function(e, i) {
      this.resizingColumnIndex = i;
      this.setDataSetVisibleColFieldAttr({
        dataSet: this.dataSet,
        colFieldIndex: i,
        attr: {
          isResizing: true
        }
      });
      document.addEventListener("mousemove", this.resizeHeaderMouseMove);
      document.addEventListener("mouseup", this.resizeHeaderMouseUp);
    },
    resizeHeaderMouseMove: function(e) {
      let i = this.resizingColumnIndex;
      if (i != -1 && this.visibleColFields[i].isResizing) {
        let widthComputed =
          this.visibleColFields[i].width + parseInt(e.movementX);
        widthComputed = widthComputed <= 30 ? 30 : widthComputed;
        this.setDataSetVisibleColFieldAttr({
          dataSet: this.dataSet,
          colFieldIndex: i,
          attr: {
            width: widthComputed
          }
        });
      }
    },
    resizeHeaderMouseUp: function() {
      this.resizingColumnIndex = -1;
      for (let i = 0; i < this.visibleColFields.length; i++) {
        this.setDataSetVisibleColFieldAttr({
          dataSet: this.dataSet,
          colFieldIndex: i,
          attr: {
            isResizing: false
          }
        });
      }
      document.removeEventListener("mousemove", this.resizeHeaderMouseMove);
      document.removeEventListener("mouseup", this.resizeHeaderMouseUp);
    },
    setColFieldOrder: function(colField, colFieldNew) {
      let payload = {
        dataSet: this.dataSet,
        colField: colField,
        colFieldNew: colFieldNew,
        setCurrent: true
      };
      this.setColFieldOrd(payload)
    },
    isSortColFieldExists: function(colField) {
      return this.sortColFields.find(
        item => item.dataFieldIdent === colField.dataFieldIdent
      )
        ? true
        : false;
    },
    setSortColFieldOrder: function(sortColField, sortColFieldNew) {
      let payload = {
        dataSet: this.dataSet,
        sortColField: sortColField,
        sortColFieldNew: sortColFieldNew,
        setCurrent: true
      };
      this.setSortColFieldOrd(payload);
    },
    onColFieldVisibleChange: function(event, colField) {
      let isVisible = event.target.checked ? 1 : 0;
      let payload = {
        colField: colField,
        isVisible: isVisible,
        layout: this.layout,
        dataSet: this.dataSet
      };
      this.setColFieldVisibility(payload);
    },
    colFieldUp: function() {
      let colFieldNew
      for (let i = 0; i < this.colFields.length; i++) {
        if (i >= this.currentColFieldIndex) break
        if (this.colFields[i].placement === 'default')
          colFieldNew = this.colFields[i]
      }
      this.setColFieldOrder(this.currentColField, colFieldNew)
    },
    colFieldDown: function() {
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'default' && i > this.currentColFieldIndex)
      this.setColFieldOrder(this.currentColField, colFieldNew)
    },
    colFieldLockedLeftUp: function() {
      let colFieldNew
      for (let i = 0; i < this.colFields.length; i++) {
        if (i >= this.currentColFieldLockedLeftIndex) break
        if (this.colFields[i].placement === 'left')
          colFieldNew = this.colFields[i]
      }
      if (colFieldNew)
        this.setColFieldLockedLeftOrd({
          dataSet: this.dataSet,
          colField: this.currentColFieldLockedLeft, 
          colFieldNew: colFieldNew,
          setCurrent: true
        })
    },
    colFieldLockedLeftDown: function() {
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'left' && i > this.currentColFieldLockedLeftIndex)
      if (colFieldNew)
        this.setColFieldLockedLeftOrd({
          dataSet: this.dataSet,
          colField: this.currentColFieldLockedLeft, 
          colFieldNew: colFieldNew,
          setCurrent: true
        })
    },
    colFieldLockedRightUp: function() {
      let colFieldNew
      for (let i = 0; i < this.colFields.length; i++) {
        if (i >= this.currentColFieldLockedRightIndex) break
        if (this.colFields[i].placement === 'right')
          colFieldNew = this.colFields[i]
      }
      if (colFieldNew)
        this.setColFieldLockedRightOrd({
          dataSet: this.dataSet,
          colField: this.currentColFieldLockedRight, 
          colFieldNew: colFieldNew,
          setCurrent: true
        })
    },
    colFieldLockedRightDown: function() {
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'right' && i > this.currentColFieldLockedRightIndex)
      if (colFieldNew)
        this.setColFieldLockedRightOrd({
          dataSet: this.dataSet,
          colField: this.currentColFieldLockedRight, 
          colFieldNew: colFieldNew,
          setCurrent: true
        })
    },
    sortColFieldUp: function() {
      this.setSortColFieldOrder(
        this.currentSortColField,
        this.sortColFields[this.currentSortColFieldIndex - 1]
      );
    },
    sortColFieldDown: function() {
      this.setSortColFieldOrder(
        this.currentSortColField,
        this.sortColFields[this.currentSortColFieldIndex + 1]
      );
    },
    onClickColField: function(event, colField) {
      this.setCurrentColField({ dataSet: this.dataSet, colField: colField });
    },
    onClickColFieldLockedLeft: function(event, colField) {
      this.setCurrentColFieldLockedLeft({ dataSet: this.dataSet, colField: colField })
    },
    onClickColFieldLockedRight: function(event, colField) {
      this.setCurrentColFieldLockedRight({ dataSet: this.dataSet, colField: colField })
    },
    onClickSortColField: function(event, sortColField) {
      this.setCurrentSortColField({
        dataSet: this.dataSet,
        sortColField: sortColField
      });
    },
    setColFieldsVisibilityAll: function(event, isVisible) {
      let layout = this.layout
      let dataSet = this.dataSet
      this.colFields.forEach(colField => {
        this.setColFieldVisibility({ colField, isVisible, layout, dataSet });
      });
    },
    reverseColFieldsVisibility: function() {
      this.colFields.forEach(colField => {
        this.setColFieldVisibility({
          colField: colField,
          isVisible: colField.isVisible === 1 ? 0 : 1,
          layout: this.layout,
          dataSet: this.dataSet
        });
      });
    },
    addSortColField: function() {
      this.addSortColFieldToSortIdent({
        dataSet: this.dataSet,
        colField: this.currentColField
      });
      let newIndex = this.currentColFieldIndex + 1 === this.colFields.length ? this.currentColFieldIndex : this.currentColFieldIndex + 1
      this.setCurrentColField({
        dataSet: this.dataSet,
        colField: this.colFields[newIndex]
      });
    },
    removeSortColField: function() {
      if (this.sortColFields.length <= 0) return;
      this.deleteSortColField({
        dataSet: this.dataSet,
        sortColField: this.currentSortColField
      });
    },
    setSortColFieldAsc: function(event, sortColField) {
      this.setSortColFieldsIsDesc({dataSet: this.dataSet, sortColField: sortColField, isDesc: 0});
    },
    setSortColFieldDesc: function(event, sortColField) {
      this.setSortColFieldsIsDesc({dataSet: this.dataSet, sortColField: sortColField, isDesc: 1});
    },
    getSortColField: function(dataFieldIdent) {
      if(this.sortColFields != null) {
        let index = this.getSortColFieldIndex(dataFieldIdent)
        return index > -1 ? this.sortColFields[index] : null
      }
    },
    getSortColFieldIndex: function(dataFieldIdent) {
      if(this.sortColFields != null) {
        return this.sortColFields.findIndex(
          item => item.dataFieldIdent === dataFieldIdent
        );
      }
    },
    getSortColFieldIsDesc: function(dataFieldIdent) {
      let colField = this.getSortColField(dataFieldIdent);
      return colField ? colField.isDesc : null;
    },
    getSortColFieldOrd: function(dataFieldIdent) {
      return this.getSortColFieldIndex(dataFieldIdent) + 1
    },
    onDragStartColField: function(evt, colField) {
      this.draggingColField = colField;
      this.setCurrentColField({ dataSet: this.dataSet, colField: colField });
    },
    onDragEndColField: function() {
      this.draggingColField = null
    },
    onDragStartColFieldLockedDefault: function(evt) {
      const colField = this.colFieldsLockedDefault[evt.oldIndex]
      this.draggingColField = colField;
      this.setCurrentColField({ dataSet: this.dataSet, colField: colField });
    },
    onDragEndColFieldLockedDefault: function(evt) {
      const to = evt.to.className
      const useVisible = evt.to.dataset.usevisible === 'true'
      if (to.includes('c-locks-default'))
        this.moveColField('default', 'default', evt.newIndex, useVisible)
      if (to.includes('c-locks-left'))
        this.moveColField('default', 'left', evt.newIndex, useVisible)
      if (to.includes('c-locks-right'))
        this.moveColField('default', 'right', evt.newIndex, useVisible)
      this.draggingColField = null;
    },
    onDragStartColFieldLockedLeft: function(evt) {
      const colFieldLockedLeft = this.colFieldsLockedLeft[evt.oldIndex]
      this.draggingColFieldLockedLeft = colFieldLockedLeft
      this.setCurrentColFieldLockedLeft({
        dataSet: this.dataSet,
        colField: colFieldLockedLeft
      })
    },
    onDragEndColFieldLockedLeft: function(evt) {
      const to = evt.to.className
      const useVisible = evt.to.dataset.usevisible === 'true'
      if (to.includes('c-locks-default'))
        this.moveColField('left', 'default', evt.newIndex, useVisible)
      if (to.includes('c-locks-left'))
        this.moveColField('left', 'left', evt.newIndex, useVisible)
      if (to.includes('c-locks-right'))
        this.moveColField('left', 'right', evt.newIndex, useVisible)
      this.draggingColFieldLockedLeft = null
    },
    onDragStartColFieldLockedRight: function(evt) {
      const colFieldLockedRight = this.colFieldsLockedRight[evt.oldIndex]
      this.draggingColFieldLockedRight = colFieldLockedRight
      this.setCurrentColFieldLockedRight({
        dataSet: this.dataSet,
        colField: colFieldLockedRight
      })
    },
    onDragEndColFieldLockedRight: function(evt) {
      const to = evt.to.className
      const useVisible = evt.to.dataset.usevisible === 'true'
      if (to.includes('c-locks-left'))
        this.moveColField('right', 'left', evt.newIndex, useVisible)
      if (to.includes('c-locks-default'))
        this.moveColField('right', 'default', evt.newIndex, useVisible)
      if (to.includes('c-locks-right'))
        this.moveColField('right', 'right', evt.newIndex, useVisible)
      this.draggingColFieldLockedRight = null
    },
    moveColField: function(from, to, toIdx, useVisible) {
      let colField

      if (from === 'left' && to === 'left') {
        colField = useVisible ? this.visibleColFieldsLockedLeft[toIdx] : this.colFieldsLockedLeft[toIdx]
        this.setColFieldLockedLeftOrd({
          dataSet: this.dataSet,
          colField: this.draggingColFieldLockedLeft, 
          colFieldNew: colField,
          setCurrent: true
        })
      }
      if (from === 'left' && to === 'default') {
        colField = useVisible ? this.visibleColFieldsLockedDefault[toIdx] : this.colFieldsLockedDefault[toIdx]
        this.removeColFieldLockedLeft('default')
        if (colField != undefined)
          this.setColFieldOrder(this.draggingColFieldLockedLeft, colField);
      }
      if (from === 'left' && to === 'right') {
        colField = useVisible ? this.visibleColFieldsLockedRight[toIdx] : this.colFieldsLockedRight[toIdx]
        this.removeColFieldLockedLeft('right')
        if (colField != undefined)
          this.setColFieldLockedRightOrd({
            dataSet: this.dataSet,
            colField: this.draggingColFieldLockedLeft, 
            colFieldNew: colField,
            setCurrent: true
          })
      }
      if (from === 'default' && to === 'left') {
        colField = useVisible ? this.visibleColFieldsLockedLeft[toIdx] : this.colFieldsLockedLeft[toIdx]
        this.addColFieldLockedLeft(this.currentColFieldIndex)
        if (colField != undefined)
          this.setColFieldLockedLeftOrd({
            dataSet: this.dataSet,
            colField: this.draggingColField, 
            colFieldNew: colField,
            setCurrent: true
          })
      }
      if (from === 'default' && to === 'default') {
        colField = useVisible ? this.visibleColFieldsLockedDefault[toIdx] : this.colFieldsLockedDefault[toIdx]
        this.setColFieldOrder(this.draggingColField, colField);
      }
      if (from === 'default' && to === 'right') {
        colField = useVisible ? this.visibleColFieldsLockedRight[toIdx] : this.colFieldsLockedRight[toIdx]
        this.addColFieldLockedRight(this.currentColFieldIndex)
        if (colField != undefined)
          this.setColFieldLockedRightOrd({
            dataSet: this.dataSet,
            colField: this.draggingColField, 
            colFieldNew: colField,
            setCurrent: true
          })
      }
      if (from === 'right' && to === 'left') {
        colField = useVisible ? this.visibleColFieldsLockedLeft[toIdx] : this.colFieldsLockedLeft[toIdx]
        this.removeColFieldLockedRight('left')
        if (colField != undefined)
          this.setColFieldLockedLeftOrd({
            dataSet: this.dataSet,
            colField: this.draggingColFieldLockedRight, 
            colFieldNew: colField,
            setCurrent: true
          })
      }
      if (from === 'right' && to === 'default') {
        colField = useVisible ? this.visibleColFieldsLockedDefault[toIdx] : this.colFieldsLockedDefault[toIdx]
        this.removeColFieldLockedRight('default')
        if (colField != undefined)
          this.setColFieldOrder(this.draggingColFieldLockedRight, colField);
      }
      if (from === 'right' && to === 'right') {
        colField = useVisible ? this.visibleColFieldsLockedRight[toIdx] : this.colFieldsLockedRight[toIdx]
        this.setColFieldLockedRightOrd({
          dataSet: this.dataSet,
          colField: this.draggingColFieldLockedRight, 
          colFieldNew: colField,
          setCurrent: true
        })
      }
    },
    sortColFieldDragStart: function($e, colField) {
      this.draggingSortColField = colField
      this.setCurrentSortColField({
        dataSet: this.dataSet,
        sortColField: colField
      });
    },
    sortColFieldDragEnd: function() {
      this.draggingSortColField = null;
    },
    colFieldDrop: function() {
      if (this.draggingSortColField) this.removeSortColField();
    },
    colFieldDropOnList: function() {
      if (this.draggingSortColField) this.removeSortColField();
    },
    sortColFieldDrop: function(event, sortColField) {
      if (this.draggingSortColField)
        this.setSortColFieldOrder(this.draggingSortColField, sortColField);
      if (this.draggingColField && !this.isSortColFieldExists(this.currentColField)) {
        this.addSortColField();
        this.setSortColFieldOrder(this.currentSortColField, sortColField);
      }
    },
    sortColFieldDropOnList: function(event) {
      let offset = Math.ceil((event.layerY - 5) / 30);
      if (this.draggingSortColField) {
        offset =
          offset > this.sortColFields.length - 1
            ? this.sortColFields.length - 1
            : offset;
        this.setSortColFieldOrder(this.draggingSortColField, this.sortColFields[offset]);
      }
      if (this.draggingColField && !this.isSortColFieldExists(this.currentColField)) {
        this.addSortColField();
        offset =
          offset > this.sortColFields.length
            ? this.sortColFields.length
            : offset;
        this.setSortColFieldOrder(this.currentSortColField, this.sortColFields[offset]);
      }
    },
    colFieldClick: function(event, colField, sortColField) {
      let isDesc = sortColField ? sortColField.isDesc : -1;
      this.setCurrentColField({ dataSet: this.dataSet, colField: colField });
      if (this.sortColFields.length > 0) 
        this.deleteAllSortColFields({ dataSet: this.dataSet });
      if (isDesc === -1) {
        this.addSortColField();
      } else if (isDesc === 0) {
        this.addSortColField();
        this.setSortColFieldsIsDesc({
          dataSet: this.dataSet,
          sortColField: this.currentSortColField,
          isDesc: 1
        });
      }
      this.refresh();
    },
    colFieldShiftClick: function(event, colField, sortColField) {
      let isDesc = sortColField ? sortColField.isDesc : -1;
      if (isDesc === -1) {
        this.setCurrentColField({ dataSet: this.dataSet, colField: colField });
        this.addSortColField();
      } else if (isDesc === 0) {
        this.setCurrentSortColField({
          dataSet: this.dataSet,
          sortColField: sortColField
        });
        this.setSortColFieldsIsDesc({
          dataSet: this.dataSet,
          sortColField: this.currentSortColField,
          isDesc: 1
        });
      } else if (isDesc === 1) {
        this.setCurrentSortColField({
          dataSet: this.dataSet,
          sortColField: sortColField
        });
        this.removeSortColField();
      }
      this.refresh();
    },
    showAdditionalInfo: function(ev, row) {
      if (this.showOneAdditionalInfoAtATime)
        this.rows.forEach(r => {
          let payload = {
            sourceKind: this.sourceKind,
            appWindowIdent: this.appWindowIdent,
            dataSet: this.dataSet,
            row: r,
            pivotCol: this.pivotCol,
            pivotRow: this.pivotRow,
            pivotRowKey: this.pivotRowKey,
            dataFieldIdent: '_showAdditionalInfo',
            dataFieldValue: r === row ? r._showAdditionalInfo === 1 ? 0 : 1 : 0
          }

          this.setDataSetFieldValue(payload)
        })
      else {
        let payload = {
          sourceKind: this.sourceKind,
          appWindowIdent: this.appWindowIdent,
          dataSet: this.dataSet,
          row: row,
          pivotCol: this.pivotCol,
          pivotRow: this.pivotRow,
          pivotRowKey: this.pivotRowKey,
          dataFieldIdent: '_showAdditionalInfo',
          dataFieldValue: row._showAdditionalInfo === 1 ? 0 : 1
        }
        this.setDataSetFieldValue(payload)
      }
    },
    getAggrField: function(dataFieldIdent){
      return this.aggrFields4Display.find(i => i.dataFieldIdent === dataFieldIdent)
    },
    addColFieldLockedLeft: function(idx) {
      this.setDataSetColFieldAttr({
        dataSet: this.dataSet,
        colFieldIndex: idx || this.currentColFieldIndex,
        attr: { placement: 'left' }
      });
      if (this.colFieldsLockedLeft.length === 1)
        this.setCurrentColFieldLockedLeft({
          dataSet: this.dataSet,
          colField: this.currentColField
        })
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'default' && i > this.currentColFieldIndex)
      if (!colFieldNew) colFieldNew = this.colFields[this.colFields.indexOf(this.colFieldsLockedDefault[this.colFieldsLockedDefault.length - 1])]
      this.setCurrentColField({ dataSet: this.dataSet, colField: colFieldNew})
    },
    removeColFieldLockedLeft: function(placement) {
      this.setDataSetColFieldAttr({
        dataSet: this.dataSet,
        colFieldIndex: this.currentColFieldLockedLeftIndex,
        attr: { placement: placement || 'default' }
      });
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'left' && i > this.currentColFieldLockedLeftIndex)
      if (!colFieldNew) colFieldNew = this.colFields[this.colFields.indexOf(this.colFieldsLockedLeft[this.colFieldsLockedLeft.length - 1])]
      this.setCurrentColFieldLockedLeft({ dataSet: this.dataSet, colField: colFieldNew})
    },
    addColFieldLockedRight: function(idx) {
      this.setDataSetColFieldAttr({
        dataSet: this.dataSet,
        colFieldIndex: idx || this.currentColFieldIndex,
        attr: { placement: 'right' }
      });
      if (this.colFieldsLockedRight.length === 1)
        this.setCurrentColFieldLockedRight({
          dataSet: this.dataSet,
          colField: this.currentColField
        })
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'default' && i > this.currentColFieldIndex)
      if (!colFieldNew) colFieldNew = this.colFields[this.colFields.indexOf(this.colFieldsLockedDefault[this.colFieldsLockedDefault.length - 1])]
      this.setCurrentColField({ dataSet: this.dataSet, colField: colFieldNew})
    },
    removeColFieldLockedRight: function(placement) {
      this.setDataSetColFieldAttr({
        dataSet: this.dataSet,
        colFieldIndex: this.currentColFieldLockedRightIndex,
        attr: { placement: placement || 'default' }
      });
      let colFieldNew = this.colFields.find((colField, i) => colField.placement === 'right' && i > this.currentColFieldLockedRightIndex)
      if (!colFieldNew) colFieldNew = this.colFields[this.colFields.indexOf(this.colFieldsLockedRight[this.colFieldsLockedRight.length - 1])]
      this.setCurrentColFieldLockedRight({ dataSet: this.dataSet, colField: colFieldNew})
    },
    toggleCurrentColFieldAggr: function($event, aggrType) {
      this.toggleDataSetAggrField({
        dataSet: this.dataSet,
        colField: this.currentColField,
        aggrType: aggrType
      })
    },
    isCurrentColFieldAggrChecked: function(aggrType) {
      return this.getAggrField(this.currentColField?.dataFieldIdent)?.aggrType === aggrType
    },
    getColFieldAggrTypeActive: function(colField) {
      return this.getAggrField(colField.dataFieldIdent)?.aggrType || ''
    }
  }
};
</script>
