import React from 'react'
import qs from 'querystring'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { compose, withHandlers, withState } from 'recompose'

import { Spinner } from '../UIComponents/index'
import { currentUserIsReviewer } from '../../redux/reviewers'

const createAnchorElement = (file, filename) => {
  const url = URL.createObjectURL(file)
  const a = document.createElement('a')

  a.href = url
  a.download = filename
  document.body.appendChild(a)

  return {
    a,
    url,
  }
}

const removeAnchorElement = (a, url) => {
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

const ZipFiles = ({ disabled, fetching, children, downloadFiles }) => (
  <Root onClick={!disabled ? downloadFiles : null}>
    {fetching ? <Spinner /> : children}
  </Root>
)

const cache = {}

const reviewerFiles = ['manuscripts', 'supplementary']
const defaultFiles = [...reviewerFiles, 'coverLetter']

const Zip = compose(
  connect((state, { collectionId }) => ({
    token: state.currentUser.user.token,
    isReviewer: currentUserIsReviewer(state, collectionId),
  })),
  withState('fetching', 'setFetching', false),
  withHandlers({
    downloadFiles: ({
      isReviewer,
      token,
      fragmentId,
      setFetching,
      archiveName,
    }) => () => {
      const getUrl = `${
        window.location.origin
      }/api/files/${fragmentId}?${qs.stringify({
        fileTypes: isReviewer ? reviewerFiles : defaultFiles,
      })}`
      if (cache[fragmentId]) {
        const fileName = archiveName || `${fragmentId}-archive.zip`

        const { a, url } = createAnchorElement(cache[fragmentId], fileName)
        a.click()
        removeAnchorElement(a, url)
      } else {
        setFetching(fetching => true)
        const xhr = new XMLHttpRequest()
        xhr.onreadystatechange = function onXhrStateChange() {
          if (this.readyState === 4) {
            setFetching(fetching => false)
            if (this.status >= 200 && this.status < 300) {
              const fileName = archiveName || `${fragmentId}-archive.zip`
              const f = new File([this.response], fileName, {
                type: 'application/zip',
              })
              cache[fragmentId] = f

              const { a, url } = createAnchorElement(f, fileName)
              a.click()
              removeAnchorElement(a, url)
            }
          }
        }
        xhr.open('GET', getUrl)
        xhr.responseType = 'blob'
        xhr.setRequestHeader('Authorization', `Bearer ${token}`)
        xhr.send()
      }
    },
  }),
)(ZipFiles)

Zip.propTypes = {
  disabled: PropTypes.bool,
  archiveName: PropTypes.string,
  fragmentId: PropTypes.string.isRequired,
}

Zip.defaultProps = {
  disabled: false,
}

export default Zip

// #region styled components
const Root = styled.div`
  align-items: center;
  cursor: pointer;
  display: flex;
  margin: 0 7px;
  width: 38px;
`
// #endregion