/* eslint-disable */
//
// Has eslint disabled because it's a node-renderer which is based on default
// node-renderer from react-sortable-tree library with minor overrides, as is
// recommended per their docs in case of severe necessity
// remote URL: https://github.com/frontend-collective/react-sortable-tree/blob/a5c67fe168db6c3f11a768909d5435d21255cb43/src/node-renderer-default.js
//
import React from 'react';
import styled from 'styled-components';
import { isDescendant } from 'react-sortable-tree';

function classNames(...classes: any[]) {
  // Use Boolean constructor as a filter callback
  // Allows for loose type truthy/falsey checks
  // Boolean("") === false;
  // Boolean(false) === false;
  // Boolean(undefined) === false;
  // Boolean(null) === false;
  // Boolean(0) === false;
  // Boolean("classname") === true;
  return classes.filter(Boolean).join(' ');
}

const Container = styled.div`
  height: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
`;

const NodeRenderer = (props: any) => {
  const {
    scaffoldBlockPxWidth,
    toggleChildrenVisibility,
    connectDragPreview,
    connectDragSource,
    isDragging,
    canDrop,
    canDrag,
    node,
    title,
    moveHandle,
    subtitle,
    draggedNode,
    path,
    treeIndex,
    isSearchMatch,
    isSearchFocus,
    className,
    style,
    didDrop,
    treeId,
    isOver, // Not needed, but preserved for other renderers
    parentNode, // Needed for dndManager
    rowDirection,
    ...otherProps
  } = props;
  const nodeMoveHandle = moveHandle || node.moveHandle;
  const nodeTitle = title || node.title;
  const nodeSubtitle = subtitle || node.subtitle;
  const rowDirectionClass = rowDirection === 'rtl' ? 'rst__rtl' : null;

  let handle;
  if (canDrag) {
    if (typeof node.children === 'function' && node.expanded) {
      // Show a loading symbol on the handle when the children are expanded
      //  and yet still defined by a function (a callback to fetch the children)
      handle = (
        <div className="rst__loadingHandle">
          <div className="rst__loadingCircle">
            {[...new Array(12)].map((_, index) => (
              <div
                  // eslint-disable-next-line react/no-array-index-key
                key={index}
                className={classNames(
                  'rst__loadingCirclePoint',
                  rowDirectionClass,
                )}
              />
            ))}
          </div>
        </div>
      );
    } else {
      // Show the handle used to initiate a drag-and-drop
      handle = connectDragSource(<div className="rst__moveHandle">{nodeMoveHandle}</div>, {
        dropEffect: 'copy',
      });
    }
  }

  const isDraggedDescendant = draggedNode && isDescendant(draggedNode, node);
  const isLandingPadActive = !didDrop && isDragging;

  let buttonStyle: {} = { left: -0.5 * scaffoldBlockPxWidth };
  if (rowDirection === 'rtl') {
    buttonStyle = { right: -0.5 * scaffoldBlockPxWidth };
  }

  return (
    <Container {...otherProps}>
      {toggleChildrenVisibility
          && node.children
          && (node.children.length > 0 || typeof node.children === 'function') && (
            <div>
              <button
                type="button"
                aria-label={node.expanded ? 'Collapse' : 'Expand'}
                className={classNames(
                  node.expanded ? 'rst__collapseButton' : 'rst__expandButton',
                  rowDirectionClass,
                )}
                style={buttonStyle}
                onClick={() => toggleChildrenVisibility({
                  node,
                  path,
                  treeIndex,
                })}
              />

              {node.expanded && !isDragging && (
                <div
                  style={{ width: scaffoldBlockPxWidth }}
                  className={classNames('rst__lineChildren', rowDirectionClass)}
                />
              )}
            </div>
      )}

      <div className={classNames('rst__rowWrapper', rowDirectionClass)}>
        {/* Set the row preview to be used during drag and drop */}
        {connectDragPreview(
          <div
            className={classNames(
              'rst__row',
              isLandingPadActive && 'rst__rowLandingPad',
              isLandingPadActive && !canDrop && 'rst__rowCancelPad',
              isSearchMatch && 'rst__rowSearchMatch',
              isSearchFocus && 'rst__rowSearchFocus',
              rowDirectionClass,
              className,
            )}
            style={{
              opacity: isDraggedDescendant ? 0.5 : 1,
              ...style,
            }}
          >
            {handle}

            <div
              className={classNames(
                'rst__rowContents',
                !canDrag && 'rst__rowContentsDragDisabled',
                rowDirectionClass,
              )}
            >
              <div className={classNames('rst__rowLabel', rowDirectionClass)}>
                <span
                  className={classNames(
                    'rst__rowTitle',
                    node.subtitle && 'rst__rowTitleWithSubtitle',
                  )}
                >
                  {typeof nodeTitle === 'function'
                    ? nodeTitle({
                      node,
                      path,
                      treeIndex,
                    })
                    : nodeTitle}
                </span>

                {nodeSubtitle && (
                <span className="rst__rowSubtitle">
                  {typeof nodeSubtitle === 'function'
                        ? nodeSubtitle({
                          node,
                          path,
                          treeIndex,
                        })
                        : nodeSubtitle}
                </span>
                )}
              </div>
            </div>
          </div>,
        )}
      </div>
    </Container>
  );
};


export default NodeRenderer;
