import PropTypes from 'prop-types'
import { PureComponent } from 'react'

/**
 * Customized function to get dimensions and position for a centered
 * popup window
 * @param  {string} url
 * @param  {string} title
 * @param  {string|number} w
 * @param  {string|number} h
 * @return {{w, h, top, left}}       Popup window
 */
// source https://stackoverflow.com/a/16861050
export function popupCenter(w, h) {
  // eslint-disable-next-line no-redeclare
  /* global screen */
  // Fixes dual-screen position
  //                      Most browsers      Firefox
  var dualScreenLeft = window.screenLeft || screen.left
  var dualScreenTop = window.screenTop || screen.top

  var width = window.innerWidth
    ? window.innerWidth
    : document.documentElement.clientWidth
      ? document.documentElement.clientWidth
      : screen.width
  var height = window.innerHeight
    ? window.innerHeight
    : document.documentElement.clientHeight
      ? document.documentElement.clientHeight
      : screen.height

  var left = width / 2 - w / 2 + dualScreenLeft
  var top = height / 2 - h / 2 + dualScreenTop
  // need to be set here to get from the OAuth opener
  return {
    w,
    h,
    top,
    left
  }
}

/**
 * Renders a popup and listen to popup events
 */
export class Popup extends PureComponent {
  constructor(props, context) {
    super(props, context)
    this.handleClose = this.handleClose.bind(this)
    this.handleUrlChange = this.handleUrlChange.bind(this)
  }

  componentDidMount() {
    this.showPopup()
  }

  componentWillUnmount() {
    this.killPopup()
  }

  handleClose(popup) {
    this.killPopup()

    const { onClose } = this.props
    if (typeof onClose === 'function') onClose(popup)
  }

  showPopup() {
    const { height, width, title, url } = this.props
    const { w, h, top, left } = popupCenter(width, height)
    /**
     * ATM we also use window.open on Native App in order to open
     * InAppBrowser. But some provider (Google for instance) will
     * block us. We need to use a SafariViewController or Chrome Custom Tab.
     * So
     */
    const popup = window.open(
      url,
      title,
      `scrollbars=yes, width=${w}, height=${h}, top=${top}, left=${left}`
    )

    if (!popup) {
      throw new Error(
        'Popup was blocked by browser. Be sure to not call showPopup asynchronously'
      )
    }

    // Puts focus on the newWindow
    if (popup.focus) {
      popup.focus()
    }

    this.startMonitoringClosing(popup)
    this.setState({ popup })
  }

  killPopup() {
    const { popup } = this.state
    this.stopMonitoringClosing()
    if (!popup.closed) popup.close()
  }

  monitorClosing(popup) {
    if (popup.closed) {
      this.stopMonitoringClosing()
      return this.handleClose(popup)
    }
  }

  /**
   * Check if window is closing every 500ms
   * @param  {Window} window
   */
  startMonitoringClosing(popup) {
    this.checkClosedInterval = setInterval(
      () => this.monitorClosing(popup),
      500
    )
  }

  stopMonitoringClosing() {
    clearInterval(this.checkClosedInterval)
  }

  handleUrlChange(event) {
    const { url } = event
    const { onUrlChange } = this.props
    if (typeof onUrlChange === 'function') onUrlChange(new URL(url))
  }

  render() {
    return null
  }
}

Popup.propTypes = {
  // Dimensions
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  title: PropTypes.string,
  url: PropTypes.string.isRequired,
  // Callbacks
  onClose: PropTypes.func,
  onMessage: PropTypes.func,
  onUrlChange: PropTypes.func
}

Popup.defaultProps = {
  title: ''
}

export default Popup
