import React, { Fragment, memo, lazy, Suspense } from 'react';
import { connect } from 'react-redux';
import Favorite from '../Favorite';
import lazyContainer from '../../../../lazyContainer';
import { hideContextMenu, showCopyModal, hideCopyModal } from './models';
import { copySelectedLayerToScreen } from 'models/component';
import { changeLayerStatus } from 'models/screen';
import { toObject } from 'utils/layer';
import { isBeLinked } from 'utils/nodes';
import { useMemo } from 'react';

const ContextMenuModal = lazyContainer(() => import(/* webpackChunkName: "context-menu" */ './ContextMenuModal'));
const CopyModal = lazyContainer(() => import(/* webpackChunkName: "copy-modal" */ './CopyModal'));
const ModuleCreateContainer = lazy(() => import(/* webpackChunkName: "module-create" */ '../Module/CreateContainer'));

function ContextMenu({
  visible,
  copyVisible,
  copyLoading,
  mode,
  type,
  top,
  left,
  show,
  lock,
  focus,
  layerOptions,
  isAdmin,
  layersSelected,
  componentsById,
  hideContextMenu,
  showCopyModal,
  hideCopyModal,
  panelOnly,
  copySelectedLayerToScreen,
  changeLayerStatus
}: {
  visible: boolean;
  copyVisible: boolean;
  copyLoading: boolean;
  mode: string;
  type: string;
  top: number;
  left: number;
  show: boolean;
  lock: boolean;
  focus: boolean;
  layerOptions: any;
  isAdmin: boolean;
  layersSelected: any;
  componentsById: {
    [x: string]: any;
  };
  panelOnly: boolean;
  hideContextMenu: () => any;
  showCopyModal: () => any;
  hideCopyModal: () => any;
  copySelectedLayerToScreen: () => any;
  changeLayerStatus: () => any;
}) {
  const id = layersSelected.length === 1 && layersSelected?.[0];

  const _isBeLinked = useMemo(() => {
    return visible && id && isBeLinked(id, componentsById);
  }, [componentsById, id, visible]);

  return (
    <Fragment>
      <ContextMenuModal
        visible={visible}
        selected={layersSelected}
        layerOptions={layerOptions}
        type={type}
        top={top}
        isBeLinked={_isBeLinked}
        left={left}
        show={show}
        lock={lock}
        focus={focus}
        isAdmin={isAdmin}
        panelOnly={panelOnly}
        onClose={hideContextMenu}
        onCrossCopy={showCopyModal}
        onClick={changeLayerStatus}
      />

      <CopyModal mode={mode} visible={copyVisible} onCancel={hideCopyModal} loading={copyLoading} onComplete={copySelectedLayerToScreen} />

      <Favorite />

      {isAdmin && (
        <Suspense fallback="">
          <ModuleCreateContainer />
        </Suspense>
      )}
    </Fragment>
  );
}

const mapStateToProps = ({ createApp, user, screensById, componentsById }) => {
  const { id, contextMenu, layersSelected, focusLayers } = createApp;
  const { visible, copyVisible, copyLoading, type, top, left, layerOptions, panelOnly } = contextMenu;
  const { userInfo } = user;
  const screen = screensById[id];
  let show;
  let lock;
  let mode = 'screen';
  let focus;
  if (screen) {
    const { layers, mobileId } = screen;
    const layersById = toObject(layers);
    show = layersSelected.every((d) => layersById[d] && layersById[d].show);
    lock = layersSelected.every((d) => layersById[d] && layersById[d].lock);
    focus = layersSelected.every((d) => focusLayers.includes(d));

    if (mobileId) {
      mode = 'mobile';
    }
  }

  return {
    visible,
    copyVisible,
    copyLoading,
    componentsById,
    show,
    lock,
    focus,
    type,
    top,
    left,
    layerOptions,
    layersSelected,
    panelOnly,
    isAdmin: userInfo.role > 0,
    mode
  };
};

const mapDispatchToProps = {
  hideContextMenu,
  showCopyModal,
  hideCopyModal,
  copySelectedLayerToScreen,
  changeLayerStatus
};

export default connect(mapStateToProps, mapDispatchToProps)(memo(ContextMenu));
