/*
 * 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 {globals} from './globals';

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);
                }

                globals.rafScheduler.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) {
                  globals.rafScheduler.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;
                globals.rafScheduler.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;
                globals.rafScheduler.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);
    }
  }
}
