import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import classnames from 'classnames';
import isUrl from 'is-url';
import Box from '@mui/material/Box';
import FormControlLabel from '@mui/material/FormControlLabel';
import { SimpleTreeView, TreeItem } from '@mui/x-tree-view';
import Checkbox from '@mui/material/Checkbox';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import OpenInNewIcon from '@mui/icons-material/OpenInNew';
import { Icon } from '@iconify/react';
import Images from '../../../images';

// BFS algorithm to find node by his ID
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const bfsSearch = (graph, targetId) => {
  const queue = [...graph];
  while (queue.length > 0) {
    const currNode = queue.shift();
    if (currNode.id === targetId) {
      return currNode;
    }
    if (currNode.children) {
      queue.push(...currNode.children);
    }
  }
  return []; // Target node not found
};
function ResourceIcon({
  icon = ''
}) {
  if (!icon) {
    return null;
  }
  if (isUrl(icon)) {
    return /*#__PURE__*/_jsx("img", {
      className: "resource-icon",
      src: icon,
      alt: "icon"
    });
  }
  return /*#__PURE__*/_jsx(Icon, {
    className: "resource-icon",
    icon: icon
  });
}
ResourceIcon.propTypes = {
  icon: PropTypes.string
};
export default function Tree({
  disabled = false,
  data = [],
  onChange = () => {},
  value = []
}) {
  const selectedNodes = value;

  // Retrieve all ids from node to his children's
  function getAllIds(node, idList = []) {
    idList.push(node.id);
    if (node.children) {
      node.children.forEach(child => getAllIds(child, idList));
    }
    return idList;
  }
  // Get IDs of all children from specific node
  const getAllChild = id => {
    return getAllIds(bfsSearch(data, id));
  };

  // Get all father IDs from specific node
  const getAllFathers = (id, list = []) => {
    const node = bfsSearch(data, id);
    if (node.parent) {
      list.push(node.parent);
      return getAllFathers(node.parent, list);
    }
    return list;
  };
  function isAllChildrenChecked(node, list) {
    const allChild = getAllChild(node.id);
    const nodeIdIndex = allChild.indexOf(node.id);
    allChild.splice(nodeIdIndex, 1);
    return allChild.every(nodeId => selectedNodes.concat(list).includes(nodeId));
  }
  const handleNodeSelect = (event, nodeId) => {
    event.stopPropagation();
    const allChild = getAllChild(nodeId);
    const fathers = getAllFathers(nodeId);
    if (selectedNodes.includes(nodeId)) {
      // Need to de-check
      const newValue = selectedNodes.filter(id => !allChild.concat(fathers).includes(id));
      onChange(newValue);
    } else {
      // Need to check
      const ToBeChecked = allChild;
      for (let i = 0; i < fathers.length; ++i) {
        if (isAllChildrenChecked(bfsSearch(data, fathers[i]), ToBeChecked)) {
          ToBeChecked.push(fathers[i]);
        }
      }
      onChange([...selectedNodes].concat(ToBeChecked));
    }
  };
  const stopExpand = event => {
    // prevent the click event from propagating to the checkbox
    event.stopPropagation();
  };
  const hadChildren = data.some(node => node.children?.length > 0);
  const renderTree = node => {
    const checked = selectedNodes.indexOf(node.id) !== -1;
    const hasChildren = Array.isArray(node.children);
    const allChild = getAllChild(node.id);
    const indeterminate = hasChildren && !checked && selectedNodes.some(id => allChild.includes(id));
    return /*#__PURE__*/_jsx(TreeItem, {
      itemId: node.id,
      label: /*#__PURE__*/_jsx(FormControlLabel, {
        onClick: stopExpand,
        control: /*#__PURE__*/_jsx(Checkbox, {
          size: "small",
          checked: checked,
          indeterminate: indeterminate,
          tabIndex: -1,
          disableRipple: true,
          onClick: event => handleNodeSelect(event, node.id),
          disabled: node.disabled || disabled
        }),
        label: /*#__PURE__*/_jsxs(Box, {
          className: "content",
          children: [/*#__PURE__*/_jsxs(Box, {
            sx: {
              display: 'flex',
              alignItems: 'center'
            },
            children: [node.icon && /*#__PURE__*/_jsx(ResourceIcon, {
              icon: node.icon
            }), /*#__PURE__*/_jsx(Box, {
              className: "name",
              children: node.name
            }), node.url &&
            /*#__PURE__*/
            // eslint-disable-next-line jsx-a11y/control-has-associated-label
            _jsx("a", {
              href: node.url,
              target: "_blank",
              rel: "noreferrer",
              className: "link",
              children: /*#__PURE__*/_jsx(OpenInNewIcon, {
                className: "link-icon"
              })
            })]
          }), !!node.description && /*#__PURE__*/_jsx(Box, {
            className: "description",
            children: node.description
          }), !!node.images?.length && /*#__PURE__*/_jsx(Images, {
            className: "images",
            data: node.images,
            lazy: true
          })]
        })
      }),
      children: hasChildren ? node.children.map(renderTree) : null
    }, node.id);
  };
  return /*#__PURE__*/_jsx(StyledTreeView, {
    className: classnames(!hadChildren && 'no-children'),
    multiSelect: true,
    defaultCollapseIcon: /*#__PURE__*/_jsx(ExpandMoreIcon, {}),
    defaultExpandIcon: /*#__PURE__*/_jsx(ChevronRightIcon, {}),
    selected: selectedNodes,
    children: data.map(node => renderTree(node))
  });
}
Tree.propTypes = {
  data: PropTypes.array,
  value: PropTypes.array,
  onChange: PropTypes.func,
  disabled: PropTypes.bool
};
const StyledTreeView = styled(SimpleTreeView)`
  &.no-children {
    .MuiTreeItem-content {
      padding: 0;
      .MuiTreeItem-iconContainer {
        display: none;
      }
      .MuiTreeItem-label {
        padding-left: 0;
      }
    }
  }
  .MuiTreeItem-content {
    align-items: flex-start;
    .MuiTreeItem-iconContainer {
      transform: translateY(10px);
    }
    &.Mui-selected {
      background-color: transparent;
    }
  }
  .MuiTreeItem-label {
    cursor: default;
  }
  .MuiFormControlLabel-root {
    align-items: flex-start;
  }
  .content {
    padding-top: 6px;
  }
  .name {
    font-size: 16px;
    font-weight: 700;
  }
  .resource-icon {
    margin-right: 2px;
    font-size: 16px;
  }
  img.resource-icon {
    width: 1rem;
    height: 1rem;
  }
  .link {
    margin-left: 8px;
    font-size: 16px;
    color: ${({
  theme
}) => theme.palette.primary.main};
    display: flex;
  }
  .link-icon {
    font-size: inherit;
  }
  .description {
    font-size: 14px;
    color: ${({
  theme
}) => theme.palette.text.secondary};
  }
`;