/**
 * HeaderDrawerLayoutEngine - Calculates row placement for header items
 *
 * Prevents visual overlap by assigning items to different rows when
 * they occupy the same columns. Uses a track-based algorithm similar
 * to V1's AllDayLayoutEngine.
 *
 * Each row can hold multiple items as long as they don't overlap in columns.
 * When an item spans columns that are already occupied, it's placed in the
 * next available row.
 */

export interface IHeaderItemLayout {
  itemId: string;
  gridArea: string;        // "row / col-start / row+1 / col-end"
  startColumn: number;
  endColumn: number;
  row: number;
}

export interface IHeaderItemInput {
  id: string;
  columnStart: number;     // 0-based column index
  columnEnd: number;       // 0-based end column (inclusive)
}

export class HeaderDrawerLayoutEngine {
  private tracks: boolean[][] = [];
  private columnCount: number;

  constructor(columnCount: number) {
    this.columnCount = columnCount;
    this.reset();
  }

  /**
   * Reset tracks for new layout calculation
   */
  reset(): void {
    this.tracks = [new Array(this.columnCount).fill(false)];
  }

  /**
   * Calculate layout for all items
   * Items should be sorted by start column for optimal packing
   */
  calculateLayout(items: IHeaderItemInput[]): IHeaderItemLayout[] {
    this.reset();
    const layouts: IHeaderItemLayout[] = [];

    for (const item of items) {
      const row = this.findAvailableRow(item.columnStart, item.columnEnd);

      // Mark columns as occupied in this row
      for (let col = item.columnStart; col <= item.columnEnd; col++) {
        this.tracks[row][col] = true;
      }

      // gridArea format: "row / col-start / row+1 / col-end"
      // CSS grid uses 1-based indices
      layouts.push({
        itemId: item.id,
        gridArea: `${row + 1} / ${item.columnStart + 1} / ${row + 2} / ${item.columnEnd + 2}`,
        startColumn: item.columnStart,
        endColumn: item.columnEnd,
        row: row + 1  // 1-based for CSS
      });
    }

    return layouts;
  }

  /**
   * Calculate layout for a single new item
   * Useful for real-time drag operations
   */
  calculateSingleLayout(item: IHeaderItemInput): IHeaderItemLayout {
    const row = this.findAvailableRow(item.columnStart, item.columnEnd);

    // Mark columns as occupied
    for (let col = item.columnStart; col <= item.columnEnd; col++) {
      this.tracks[row][col] = true;
    }

    return {
      itemId: item.id,
      gridArea: `${row + 1} / ${item.columnStart + 1} / ${row + 2} / ${item.columnEnd + 2}`,
      startColumn: item.columnStart,
      endColumn: item.columnEnd,
      row: row + 1
    };
  }

  /**
   * Find the first row where all columns in range are available
   */
  private findAvailableRow(startCol: number, endCol: number): number {
    for (let row = 0; row < this.tracks.length; row++) {
      if (this.isRowAvailable(row, startCol, endCol)) {
        return row;
      }
    }

    // Add new row if all existing rows are occupied
    this.tracks.push(new Array(this.columnCount).fill(false));
    return this.tracks.length - 1;
  }

  /**
   * Check if columns in range are all available in given row
   */
  private isRowAvailable(row: number, startCol: number, endCol: number): boolean {
    for (let col = startCol; col <= endCol; col++) {
      if (this.tracks[row][col]) {
        return false;
      }
    }
    return true;
  }

  /**
   * Get the number of rows currently in use
   */
  getRowCount(): number {
    return this.tracks.length;
  }

  /**
   * Update column count (e.g., when view changes)
   */
  setColumnCount(count: number): void {
    this.columnCount = count;
    this.reset();
  }
}
