import PropTypes from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom'
import Observable from '@sanity/observable'
import observeForPreview from './observeForPreview'
import shallowEquals from 'shallow-equals'
import resize$ from './streams/resize'
import scroll$ from './streams/scroll'
import orientationChange$ from './streams/orientationChange'
import visibilityChange$ from './streams/visibilityChange'

function isVisible() {
  return !document.hidden
}

function getViewport() {
  return {
    height: window.innerHeight,
    width: window.innerWidth
  }
}

const MARGIN = 60
function contains(rect, viewport) {
  return (
    rect.top + rect.height >= MARGIN
    && rect.left + rect.width >= MARGIN
    && rect.bottom - rect.height - MARGIN <= viewport.height
    && rect.right - rect.width - MARGIN <= viewport.width
  )
}

function inViewport(element) {
  return () => contains(element.getBoundingClientRect(), getViewport())
}


export default class PreviewSubscriber extends React.PureComponent {
  static propTypes = {
    type: PropTypes.object.isRequired,
    fields: PropTypes.arrayOf(PropTypes.oneOf(['title', 'description', 'imageUrl'])),
    value: PropTypes.any.isRequired,
    children: PropTypes.func
  };

  state = {
    error: null,
    result: {snapshot: null, type: null},
    isLive: false
  }

  componentDidMount() {
    this.subscribe(this.props.value, this.props.type, this.props.fields)
  }

  componentWillUnmount() {
    this.unsubscribe()
  }

  unsubscribe() {
    if (this.subscription) {
      this.subscription.unsubscribe()
      this.subscription = null
    }
  }

  componentWillUpdate(nextProps) {
    if (!shallowEquals(nextProps.value, this.props.value)) {
      this.subscribe(nextProps.value, nextProps.type)
    }
  }

  subscribe(value, type, fields) {
    this.unsubscribe()

    const visibilityOn$ = Observable.of(isVisible())
       .merge(visibilityChange$.map(event => !event.target.hidden))

    const checkViewport = inViewport(ReactDOM.findDOMNode(this))
    const inViewport$ = resize$.merge(scroll$)
      .merge(orientationChange$)
      .map(checkViewport)

    this.subscription = visibilityOn$
      .distinctUntilChanged()
      .switchMap(on => {
        return on ? Observable.of(checkViewport()).merge(inViewport$) : Observable.of(false)
      })
      .distinctUntilChanged()
      // .do(log('in viewport', value._id))
      .switchMap(isInViewport => {
        return isInViewport
          ? observeForPreview(value, type, fields)
          : Observable.of(null)
      })
      .subscribe(result => {
        if (result) {
          this.setState({result, isLive: true})
        } else {
          this.setState({isLive: false})
        }
      })
  }

  render() {
    const {result, isLive, error} = this.state
    const {children: Child, ...props} = this.props
    return <Child snapshot={result.snapshot} type={result.type} isLive={isLive} error={error} {...props} />
  }
}

@@ -517,18 +517,30 @@
 n %7B%0A    
-he
+left: 0,%0A    r
 ight: wi
@@ -553,25 +553,37 @@
 nner
-Height,%0A    width
+Width,%0A    top: 0,%0A    bottom
 : wi
@@ -592,21 +592,22 @@
 ow.inner
-Width
+Height
 %0A  %7D%0A%7D%0A%0A
@@ -625,9 +625,10 @@
 N = 
-6
+15
 0%0Afu
@@ -634,23 +634,25 @@
 unction 
-contain
+intersect
 s(rect, 
@@ -687,28 +687,32 @@
 ect.
-top + rect.he
+left %3C= viewport.r
 ight 
-%3E=
++
  MAR
@@ -731,154 +731,127 @@
 ect.
-left + rect.width %3E= MARGIN%0A    && rect.bottom - rect.height - MARGIN %3C= viewport.height%0A    && rect.right - rect.width - MARGIN %3C= viewport.width
+right %3E= viewport.left - MARGIN%0A    && rect.top %3C= viewport.bottom + MARGIN%0A    && rect.bottom %3E= viewport.top - MARGIN
 %0A  )
@@ -904,15 +904,17 @@
  =%3E 
-contain
+intersect
 s(el
@@ -962,17 +962,16 @@
 t())%0A%7D%0A%0A
-%0A
 export d
@@ -1252,9 +1252,8 @@
 %0A  %7D
-;
 %0A%0A  
@@ -2384,36 +2384,50 @@
 .do(
-log('in viewport', value._id
+isInViewport =%3E console.log(%7BisInViewport%7D
 ))%0A 

Fix half brorked contains check