import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { MessageUtils } from '../../flow/utils.js'
export default function withContentLoader(View) {
    
    return class extends React.Component {
        static displayName = View.displayName || View.name
        static matches = View.matches
        static propTypes = {
            ...View.propTypes,
            content: PropTypes.string,  // mark as non-required
            flow: PropTypes.object.isRequired,
            message: PropTypes.object.isRequired,
        }
        constructor(props) {
            super(props)
            this.state = {
                content: undefined,
                request: undefined,
            }
        }
        componentWillMount() {
            this.updateContent(this.props)
        }
        componentWillReceiveProps(nextProps) {
            if (
                nextProps.message.content !== this.props.message.content ||
                nextProps.message.contentHash !== this.props.message.contentHash ||
                nextProps.contentView !== this.props.contentView
            ) {
                this.updateContent(nextProps)
            }
        }
        componentWillUnmount() {
            if (this.state.request) {
                this.state.request.abort()
            }
        }
        updateContent(props) {
            if (this.state.request) {
                this.state.request.abort()
            }
            // We have a few special cases where we do not need to make an HTTP request.
            if (props.message.content !== undefined) {
                return this.setState({request: undefined, content: props.message.content})
            }
            if (props.message.contentLength === 0 || props.message.contentLength === null) {
                return this.setState({request: undefined, content: ""})
            }
            let requestUrl = MessageUtils.getContentURL(props.flow, props.message, props.contentView)
            // We use XMLHttpRequest instead of fetch() because fetch() is not (yet) abortable.
            let request = new XMLHttpRequest();
            request.addEventListener("load", this.requestComplete.bind(this, request));
            request.addEventListener("error", this.requestFailed.bind(this, request));
            request.open("GET", requestUrl);
            request.send();
            this.setState({request, content: undefined})
        }
        requestComplete(request, e) {
            if (request !== this.state.request) {
                return // Stale request
            }
            this.setState({
                content: request.responseText,
                request: undefined
            })
        }
        requestFailed(request, e) {
            if (request !== this.state.request) {
                return // Stale request
            }
            console.error(e)
            // FIXME: Better error handling
            this.setState({
                content: "Error getting content.",
                request: undefined
            })
        }
        render() {
            return this.state.content !== undefined ? (