import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { translate } from '@arcblock/ux/lib/Locale/util';
import SessionPermission from '@arcblock/ux/lib/SessionPermission';
import { Icon } from '@iconify/react';
import { Close as CloseIcon } from '@mui/icons-material';
import { Box, ClickAwayListener, Fade, IconButton, Paper } from '@mui/material';
import { useMemoizedFn } from 'ahooks';
import PropTypes from 'prop-types';
import { use } from 'react';
import InstallerItem from './installer-item';
import translations from './locales';
import useComponentInstalled from './use-component-installed';

function ComponentInstaller({
  warnIcon = null,
  did,
  noPermissionMute = false,
  onInstalled = null,
  onError = null,
  children,
  closeByOutSize = false,
  onClose = null,
  fallback = null,
  disabled = false,
  roles = ['owner', 'admin'],
}) {
  const { locale } = useLocaleContext();
  const t = useMemoizedFn((key, data = {}) => {
    return translate(translations, key, locale, 'en', data);
  });
  const { installed, optComponents, installStatus, definedInBlockletYML } = useComponentInstalled({
    did,
    onInstalled,
    onError,
  });
  const sessionCtx = use(SessionContext);

  const handleClose = () => {
    onClose?.(false);
  };

  if (disabled) {
    return children;
  }

  return (
    <SessionPermission session={sessionCtx?.session} roles={roles}>
      {({ hasPermission }) => {
        if (installed) {
          return children;
        }
        if (noPermissionMute && !hasPermission) {
          return fallback || null;
        }
        if (typeof children === 'function') {
          return (
            <>
              {fallback}
              {children({
                hasPermission,
                optComponents,
                installStatus,
              })}
            </>
          );
        }
        // not installed, but has permission, can install directly
        return (
          <>
            {fallback}
            <ClickAwayListener
              onClickAway={(e) => {
                e.preventDefault();
                e.stopPropagation();
                if (closeByOutSize) {
                  handleClose();
                }
              }}>
              <Fade in timeout={350}>
                <Paper
                  variant="outlined"
                  sx={{
                    position: 'fixed',
                    top: 20,
                    right: 20,
                    zIndex: 3000,
                    borderRadius: 1.5,
                    width: 400,
                    maxWidth: '90vw',
                    borderColor: 'divider',
                    border: '0 !important',
                    fontSize: '14px',
                    textAlign: 'left',
                    boxShadow: ({ palette }) =>
                      `0px 8px 16px 0px ${palette.grey[100]}, 0px 0px 0px 1px ${palette.grey[100]}`,
                  }}>
                  {!definedInBlockletYML ? (
                    <Box sx={{ display: 'flex', flexDirection: 'column' }}>
                      <Box
                        sx={{
                          padding: '20px 24px',
                          marginLeft: 0,
                          display: 'flex',
                          alignItems: 'center',
                          flexDirection: 'row',
                          justifyContent: 'flex-start',
                        }}>
                        {warnIcon || <Icon icon="mdi:warning-box" style={{ color: 'yellowgreen', fontSize: 24 }} />}
                        <Box sx={{ marginLeft: 1, fontSize: '16px', fontWeight: 'bold' }}>
                          {t('componentInstallerTitle')}
                        </Box>
                        <Box sx={{ flex: 1 }} />
                        {onClose ? (
                          <IconButton variant="outlined" className="button" onClick={handleClose}>
                            <CloseIcon />
                          </IconButton>
                        ) : null}
                      </Box>
                      <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} />
                      <Box sx={{ padding: '20px 24px', marginTop: 0 }}>
                        {t('componentInstallerNoDefinedInBlockletYML')}: {did}
                      </Box>
                    </Box>
                  ) : (
                    <Box sx={{ display: 'flex', flexDirection: 'column' }}>
                      <Box
                        sx={{
                          padding: '20px 24px',
                          marginLeft: 0,
                          display: 'flex',
                          flexDirection: 'row',
                          alignItems: 'center',
                          justifyContent: 'flex-start',
                        }}>
                        {warnIcon || <Icon icon="mdi:warning-box" style={{ color: 'yellowgreen', fontSize: 24 }} />}
                        <Box sx={{ marginLeft: 1, fontSize: '16px', fontWeight: 'bold' }}>
                          {t('componentInstallerTitle')}
                        </Box>
                        <Box sx={{ flex: 1 }} />
                        {onClose ? (
                          <IconButton variant="outlined" className="button" onClick={handleClose}>
                            <CloseIcon />
                          </IconButton>
                        ) : null}
                      </Box>
                      <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} />
                      <Box sx={{ maxHeight: '70vh', overflowY: 'auto' }}>
                        {optComponents.map((optionalComponent, index) => {
                          return (
                            <InstallerItem
                              t={t}
                              key={optionalComponent.meta?.did || index}
                              hasPermission={hasPermission}
                              index={index}
                              optionalComponent={optionalComponent}
                              installStatus={installStatus[optionalComponent.meta?.did]}
                            />
                          );
                        })}
                      </Box>
                      {hasPermission ? null : (
                        <>
                          <Box sx={{ width: '100%', height: '1px', backgroundColor: 'grey.100' }} />
                          <Box sx={{ padding: '20px 24px' }}>
                            <Box sx={{ opacity: 1 }}>{t('componentInstallerSuggestions')}</Box>
                          </Box>
                        </>
                      )}
                    </Box>
                  )}
                </Paper>
              </Fade>
            </ClickAwayListener>
          </>
        );
      }}
    </SessionPermission>
  );
}

ComponentInstaller.propTypes = {
  disabled: PropTypes.bool,
  warnIcon: PropTypes.node,
  did: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]).isRequired,
  noPermissionMute: PropTypes.bool,
  onInstalled: PropTypes.func,
  onError: PropTypes.func,
  children: PropTypes.any.isRequired,
  closeByOutSize: PropTypes.bool,
  onClose: PropTypes.func,
  fallback: PropTypes.node,
  roles: PropTypes.array,
};

export default function WrapComponentInstaller(props) {
  if (window.blocklet) {
    return <ComponentInstaller {...props} />;
  }

  return props.children;
}

WrapComponentInstaller.propTypes = {
  ...ComponentInstaller.propTypes,
  children: PropTypes.any.isRequired,
};
