import { ChangeDetectionStrategy, Component, input, output, TemplateRef, ViewEncapsulation } from '@angular/core';
import { CdkDragDrop, CdkDropList, CdkDrag, moveItemInArray } from '@angular/cdk/drag-drop';
import { NgTemplateOutlet } from '@angular/common';

@Component({
  selector: 'fast-sortable',
  imports: [CdkDropList, CdkDrag, NgTemplateOutlet],
  template: `
    <div cdkDropList (cdkDropListDropped)="drop($event)">
      @for (item of items(); track $index) {
        <div cdkDrag class="cursor-pointer" [cdkDragPreviewContainer]="'parent'" (cdkDragStarted)="onDragStarted()" (cdkDragEnded)="onDragEnded()">
          <div class="bg-base-gray-500 dark:bg-alt-gray-500">
            @if (itemTemplate()) {
              <ng-container  *ngTemplateOutlet="itemTemplate(); context: { item: item, $implicit: item }" />
            } @else {
              {{ item }}
            }
          </div>
        </div>
      }
    </div>
  `,
  styles: [`
    body.dragging-active * {
      cursor: pointer;
    }
  `],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class FastSortableComponent<T> {
  items = input<T[]>([]);
  itemTemplate = input<TemplateRef<{ item: T; $implicit: T }> | null>(null);
  itemsChange = output<T[]>();
  orderChanged = output<CdkDragDrop<T[]>>();

  onDragStarted() {
    document.body.classList.add('dragging-active');
  }

  onDragEnded() {
    document.body.classList.remove('dragging-active');
  }

  drop(event: CdkDragDrop<T[]>) {
    if (event.previousIndex === event.currentIndex)
      return;

    const itemsCopy = [...this.items()];
    moveItemInArray(itemsCopy, event.previousIndex, event.currentIndex);
    this.itemsChange.emit(itemsCopy);
    this.orderChanged.emit(event);
  }
}
