import React from 'react'
import {connect} from 'react-redux'
import $editor from 'weblium/editor'

const getUrlByRef = (ref, options) => ref
const getErrorComponent = (error) => (props) => <div>{'' + error}</div>
const getBlockIdByHash = () => {}

@connect(({blocks}, {id}) => {
  return {
    reduxContent: _.get([id, 'content'])(blocks)
  }
})

class PreviewBlock extends React.Component {
  componentDidMount() {
    const {reduxContent, content, id, dispatch, modifier} = this.props
    dispatch({
      type: 'FETCH_BLOCK_FULFILLED',
      payload: {
        id,
        block: {content: reduxContent || content, modifier: JSON.stringify(modifier)},
      },
    })
    global.getSandboxView = this.getSandboxView
  }

  onUpdateBlockContent = content => {
    const {dispatch, id} = this.props
    dispatch({type: 'UPDATE_BLOCK', payload: {id, block: {content}}})
  }

  getSandboxView = () => require('block').default

  render() {
    const {
      Component,
      id,
      reduxContent,
      content: localContent,
      blockLoaded,
    } = this.props
    const content = reduxContent || localContent
    const $block = {
      content,
      sandbox: true,
      id,
      getUrlByRef,
      getErrorComponent,
      getBlockIdByHash,
    }
    return blockLoaded
      ? (
        <Component block={{content, id}}
                   id={id}
                   $block={$block}
                   layoutContext={{}}
                   content={content}
                   onUpdateBlockContent={this.onUpdateBlockContent}
        />
      ) : (
        <div>Loading</div>
        )
  }
}

class PreviewBlocks extends React.Component {
  componentWillMount() {
    this.buildBlocks()
  }

  componentDidMount() {
    if (module.hot) {
      module.hot.accept(['block', 'weblium/block-content', 'weblium/block-modifier'], () => {
        this.buildBlocks()
        this.updateBlocks()
      })
    }
  }

  buildBlocks = () => {
    const Block = require('block').default
    const blockContent = require('weblium/block-content')
    const blockModifier = require('weblium/block-modifier')
    this.Component = $editor.viewEnhancer(Block)
    const modifiers = _.negate(_.isArray)(blockModifier) ? [blockModifier] : blockModifier
    const contents = _.negate(_.isArray)(blockContent) ? [blockContent] : blockContent
    const data = _.zip(modifiers, contents)
    this.blocks =  _.map(([modifier, content]) => ({modifier, content: {...Block.defaultContent, ...content}}))(data)
  }

  updateBlocks = () => {
    const {dispatch} = this.props
    this.blocks.forEach((block, index) => {
      const {content, modifier} = block
      dispatch({type: 'UPDATE_BLOCK', payload: {id: "" + index, block: {content, modifier: JSON.stringify(modifier)}}})
    })
  }

  render() {
    const {dispatch, blocks, distorted} = this.props
    const {DistortionContext} = $editor
    const blockComponents = this.blocks.map((block, index) => {
      const blockLoaded = blocks[index]
      const {content, modifier} = block
      return (
        <PreviewBlock
          key={index}
          id={'' + index}
          Component={this.Component}
          dispatch={dispatch}
          blockLoaded={blockLoaded}
          distorted={distorted}
          content={content}
          modifier={modifier}
        />
      )
    })
    return DistortionContext
      ? (
        <DistortionContext.Provider value={{distorted}}>
          {blockComponents}
        </DistortionContext.Provider>
      ) : blockComponents
  }
}
export default connect(_.pick(['blocks', 'distorted']))(PreviewBlocks)
