/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import m from 'mithril';

import {DropDirection} from '../common/dragndrop_logic';
import {raf} from '../core/raf_scheduler';

export interface ReorderableCell {
  content: m.Children;
  extraClass?: string;
}

export interface ReorderableCellGroupAttrs {
  cells: ReorderableCell[];
  onReorder: (from: number, to: number, side: DropDirection) => void;
}

const placeholderElement = document.createElement('span');

// A component that renders a group of cells on the same row that can be
// reordered between each other by using drag'n'drop.
//
// On completed reorder, a callback is fired.
export class ReorderableCellGroup implements
    m.ClassComponent<ReorderableCellGroupAttrs> {
  // Index of a cell being dragged.
  draggingFrom: number = -1;

  // Index of a cell cursor is hovering over.
  draggingTo: number = -1;

  // Whether the cursor hovering on the left or right side of the element: used
  // to add the dragged element either before or after the drop target.
  dropDirection: DropDirection = 'left';

  // Auxillary array used to count entrances into `dragenter` event: these are
  // incremented not only when hovering over a cell, but also for any child of
  // the tree.
  enterCounters: number[] = [];

  getClassForIndex(index: number): string {
    if (this.draggingFrom === index) {
      return 'dragged';
    }
    if (this.draggingTo === index) {
      return this.dropDirection === 'left' ? 'highlight-left' :
                                             'highlight-right';
    }
    return '';
  }

  view(vnode: m.Vnode<ReorderableCellGroupAttrs>): m.Children {
    return vnode.attrs.cells.map(
        (cell, index) => m(
            `td.reorderable-cell${cell.extraClass ?? ''}`,
            {
              draggable: 'draggable',
              class: this.getClassForIndex(index),
              ondragstart: (e: DragEvent) => {
                this.draggingFrom = index;
                if (e.dataTransfer !== null) {
                  e.dataTransfer.setDragImage(placeholderElement, 0, 0);
                }

                raf.scheduleFullRedraw();
              },
              ondragover: (e: DragEvent) => {
                let target = e.target as HTMLElement;
                if (this.draggingFrom === index || this.draggingFrom === -1) {
                  // Don't do anything when hovering on the same cell that's
                  // been dragged, or when dragging something other than the
                  // cell from the same group
                  return;
                }

                while (target.tagName.toLowerCase() !== 'td' &&
                       target.parentElement !== null) {
                  target = target.parentElement;
                }

                // When hovering over cell on the right half, the cell will be
                // moved to the right of it, vice versa for the left side. This
                // is done such that it's possible to put dragged cell to every
                // possible position.
                const offset = e.clientX - target.getBoundingClientRect().x;
                const newDropDirection =
                    (offset > target.clientWidth / 2) ? 'right' : 'left';
                const redraw = (newDropDirection !== this.dropDirection) ||
                    (index !== this.draggingTo);
                this.dropDirection = newDropDirection;
                this.draggingTo = index;


                if (redraw) {
                  raf.scheduleFullRedraw();
                }
              },
              ondragenter: (e: DragEvent) => {
                this.enterCounters[index]++;

                if (this.enterCounters[index] === 1 &&
                    e.dataTransfer !== null) {
                  e.dataTransfer.dropEffect = 'move';
                }
              },
              ondragleave: (e: DragEvent) => {
                this.enterCounters[index]--;
                if (this.draggingFrom === -1 || this.enterCounters[index] > 0) {
                  return;
                }

                if (e.dataTransfer !== null) {
                  e.dataTransfer.dropEffect = 'none';
                }

                this.draggingTo = -1;
                raf.scheduleFullRedraw();
              },
              ondragend: () => {
                if (this.draggingTo !== this.draggingFrom &&
                    this.draggingTo !== -1) {
                  vnode.attrs.onReorder(
                      this.draggingFrom, this.draggingTo, this.dropDirection);
                }

                this.draggingFrom = -1;
                this.draggingTo = -1;
                raf.scheduleFullRedraw();
              },
            },
            cell.content));
  }

  oncreate(vnode: m.VnodeDOM<ReorderableCellGroupAttrs, this>) {
    this.enterCounters = Array(vnode.attrs.cells.length).fill(0);
  }

  onupdate(vnode: m.VnodeDOM<ReorderableCellGroupAttrs, this>) {
    if (this.enterCounters.length !== vnode.attrs.cells.length) {
      this.enterCounters = Array(vnode.attrs.cells.length).fill(0);
    }
  }
}
