React = require 'react'
createClass = require 'create-react-class'
PropTypes = require 'prop-types'

{iframe} = React.DOM

###
  @type - OPTIONAL - String
    file type contained within the iframe

  @src - REQUIRED - String
    the source of the document to be loaded in the iframe

  @id - OPTIONAL - String
    the id attribute used on the iframe

  @name - OPTIONAL - String
    the name attribute used on the string. Also used when accessing frames[]

  @className - OPTIONAL - String
    the CSS class set to the iframe

  @height - OPTIONAL - String | Number
    a fixed height for the container

  @width - OPTIONAL - String | Number 
    a fixed width for the container

  @queryParams - OPTIONAL - Object
    query params passed with iframe request

  @resizeContentAfterLoad - OPTIONAL - Function
    fired when the iframe finishes loading. This can be used to set a fixed height on a parent container in order to match the height of the embedded content. This is useful because iframes will not take the height of their content by default

  @requestClass - REQUIRED - Function
    required function that contains the server request class used for making service calls
###


IframeEmbedder = createClass

  displayName: 'IframeEmbedder'

  propTypes:
    type: PropTypes.string
    src: PropTypes.string.isRequired
    id: PropTypes.string
    name: PropTypes.string
    className: PropTypes.string
    height: PropTypes.oneOfType [
      PropTypes.string
      PropTypes.number
    ]
    width: PropTypes.oneOfType [
      PropTypes.string
      PropTypes.number
    ]
    resizeContentAfterLoad: PropTypes.func
    queryParams: PropTypes.object
    requestClass: PropTypes.func.isRequired

  getDefaultProps: ->
    height: '100%'
    width: '100%'
    className: 'iframe-embedded'
    type: ''
    id: ''
    name: ''

  render: ->
    {width, height, className, id, name} = @props

    iframe {
      className: className
      src: 'about:blank'
      width: width
      height: height
      id: id
      name: name
      ref: 'embeddedFrame'
    }

  componentWillReceiveProps: (nextProps) ->
    if @props.src isnt nextProps.src
      @getDocument(nextProps)
      
  getDocument: (props) ->
    {src, queryParams, type, requestClass} = props

    new requestClass
      url: src
      data: queryParams
    .done (res) =>
      if src and res?
        # Wrap plain text
        if type?.search('text/') > -1
          unless type.search('xml') > -1 or type.search('html') > -1
            res = "<pre style='white-space: pre-wrap;'>#{res}</pre>"

        if @refs.embeddedFrame.contentDocument?
          @refs.embeddedFrame.contentDocument.open()
          @refs.embeddedFrame.contentDocument.writeln(res)
          @refs.embeddedFrame.contentDocument.close()
          @resizeContentAfterLoad()

  componentDidMount: ->
    @getDocument(@props)

  resizeContentAfterLoad: ->
    # What this does is it will size the iframe container to be the height of its content, removing the need for its own scrollbar
    # Added an extra 40px to accommodate IE scrollbar
    docHeight = @refs.embeddedFrame.contentDocument.getElementsByTagName('html')[0].scrollHeight
    @props.resizeContentAfterLoad?(docHeight + 40)

  shouldComponentUpdate: (nextProps) -> 
    @props.src isnt nextProps.src or @props.height isnt nextProps.height or @props.width isnt nextProps.width


module.exports = IframeEmbedder