import React from 'react'
import PropTypes from 'prop-types'
import { Icon, Spinner, th } from '@pubsweet/ui'
import styled, { withTheme } from 'styled-components'
import { DropTarget } from 'react-dnd'
import { NativeTypes } from 'react-dnd-html5-backend'
import { compose, getContext, withHandlers, withState } from 'recompose'
import { SortableList } from 'pubsweet-components-faraday/src/components'

import FileItem from './FileItem'
import FilePicker from './FilePicker'

const DragHandle = withTheme(({ theme }) => (
  <Handle>
    <Icon color={theme.colorPrimary} size={3}>
      chevron_up
    </Icon>
    <Icon color={theme.colorPrimary} size={3}>
      menu
    </Icon>
    <Icon color={theme.colorPrimary} size={3}>
      chevron_down
    </Icon>
  </Handle>
))

const FileSection = ({
  error,
  title,
  files,
  listId,
  isOver,
  isLast,
  isFirst,
  addFile,
  canDrop,
  moveItem,
  theme,
  isFileOver,
  removeFile,
  connectFileDrop,
  connectDropTarget,
  allowedFileExtensions,
  isFetching,
  canDropFile,
  disabledFilepicker,
  dropSortableFile,
  previewFile,
}) => (
  <DropSection
    innerRef={instance => {
      connectFileDrop(instance)
      connectDropTarget(instance)
    }}
    isFirst={isFirst}
    isLast={isLast}
    over={isFileOver || (isOver && canDrop)}
  >
    <Header>
      <PickerContainer>
        <Title>{title}</Title>
        {!isFetching[listId] ? (
          <FilePicker
            allowedFileExtensions={allowedFileExtensions}
            disabled={disabledFilepicker()}
            onUpload={addFile}
          >
            <UploadButton
              data-test={`button-upload-${listId}`}
              disabled={disabledFilepicker()}
            >
              <Icon
                color={
                  disabledFilepicker()
                    ? theme.colorSecondary
                    : theme.colorPrimary
                }
              >
                file-plus
              </Icon>
            </UploadButton>
          </FilePicker>
        ) : (
          <Spinner />
        )}
      </PickerContainer>
      <Error>{error}</Error>
    </Header>
    <SortableList
      beginDragProps={['id', 'index', 'name', 'listId']}
      dragHandle={DragHandle}
      dropItem={dropSortableFile}
      items={files}
      listId={listId}
      listItem={FileItem}
      moveItem={moveItem}
      previewFile={previewFile}
      removeFile={removeFile}
    />
    <InfoContainer>
      <span>Drag files here or use the add button.</span>
    </InfoContainer>
  </DropSection>
)

export default compose(
  withTheme,
  getContext({
    isFetching: PropTypes.object,
  }),
  withState('error', 'setError', ''),
  withHandlers({
    clearError: ({ setError }) => () => {
      setError(e => '')
    },
  }),
  withHandlers({
    setError: ({ setError, clearError }) => err => {
      setError(e => err, () => setTimeout(clearError, 3000))
    },
    disabledFilepicker: ({ files, maxFiles }) => () => files.length >= maxFiles,
  }),
  DropTarget(
    'item',
    {
      drop(
        {
          changeList,
          listId: toListId,
          maxFiles,
          files,
          setError,
          allowedFileExtensions,
        },
        monitor,
      ) {
        const { listId: fromListId, id, name } = monitor.getItem()
        const fileExtention = name.split('.')[1]

        if (
          allowedFileExtensions &&
          !allowedFileExtensions.includes(fileExtention)
        ) {
          setError('Invalid file type.')
          return
        }

        if (files.length >= maxFiles) {
          setError('No more files can be added to this section.')
          return
        }
        if (toListId === fromListId) return
        changeList(fromListId, toListId, id)
      },
      canDrop({ listId: toListId, setError }, monitor) {
        const { listId: fromListId } = monitor.getItem()
        return toListId !== fromListId
      },
    },
    (connect, monitor) => ({
      connectDropTarget: connect.dropTarget(),
      isOver: monitor.isOver(),
      canDrop: monitor.canDrop(),
    }),
  ),
  DropTarget(
    NativeTypes.FILE,
    {
      drop(
        { files, maxFiles, addFile, allowedFileExtensions, setError },
        monitor,
      ) {
        const [file] = monitor.getItem().files
        const fileExtention = file.name.split('.')[1]

        if (files.length >= maxFiles) {
          setError('No more files can be added to this section.')
          return
        }

        if (
          allowedFileExtensions &&
          !allowedFileExtensions.includes(fileExtention)
        ) {
          setError('Invalid file type.')
        } else {
          addFile(file)
        }
      },
    },
    (connect, monitor) => ({
      connectFileDrop: connect.dropTarget(),
      isFileOver: monitor.isOver(),
      canDropFile: monitor.canDrop(),
    }),
  ),
)(FileSection)

// #region styles
const Error = styled.span`
  color: ${th('colorError')};
  font-size: ${th('fontSizeBaseSmall')};
  margin-right: ${th('subGridUnit')};
`

const UploadButton = styled.div`
  cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
  display: flex;
  margin-left: ${th('subGridUnit')};
`

const PickerContainer = styled.div`
  align-items: center;
  display: flex;
  flex: 1;
`

const Title = styled.span`
  margin: ${th('subGridUnit')};
  text-transform: uppercase;
`

const Header = styled.div`
  align-items: center;
  display: flex;
  justify-content: flex-start;
`

const DropSection = styled.div`
  border: ${th('borderDefault')};
  border-top: ${({ isFirst, theme }) =>
    isFirst ? theme.borderDefault : 'none'};
  border-bottom: ${({ isLast, theme }) =>
    isLast ? theme.borderDefault : `1px dashed ${theme.colorBorder}`};
  background-color: ${({ theme, over }) =>
    over ? theme.colorSecondary : theme.backgroundColorReverse};
  display: flex;
  flex-direction: column;
  padding: ${th('subGridUnit')};
`

const Handle = styled.div`
  align-items: center;
  border-right: ${th('borderDefault')};
  cursor: move;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-right: calc(${th('subGridUnit')}*2);
  padding: calc(${th('subGridUnit')}/2);
  span {
    padding: 0;
  }
`

const InfoContainer = styled.div`
  align-items: center;
  display: flex;
  height: 60px;
  justify-content: center;
  margin: calc(${th('subGridUnit')}*2) 0;

  span {
    color: ${th('colorTextPlaceholder')};
    font-size: ${th('fontSizeBaseSmall')};
  }
`
// #endregion