import React from 'react';
import {MdWidgets} from 'react-icons/md';
import posed from 'react-pose';
import {selectByDot} from "@formanta/js";

import Loading from "../../../component/LoadingSmall";

import SchemaEditor from "../../../component/Schema/EditorLoader";

import {withTheme, injectSheet} from '../../../lib/theme';

import {SaveSingle} from '../../../component/ContentStore';
import {blockName} from "../BlockName";
import {cancelPromise} from "../../cancelPromise";
import {storeBlock} from "../../../feature/Content/Stores/Block";

const styling = theme => ({
    wrapper: {
        overflow: 'hidden',
    }
});

const Wrapper = posed.div({
    hidden: {
        height: 0,
        paddingBottom: 0,
    },
    visible: {
        height: 'auto',
        paddingBottom: '3px',
    }
});

const initialState = {
    block: {},
    waitingForLoading: false,
    title: false,
    loaded: false,
    hasSchema: false
};

class ContentBlock extends React.Component {

    state = initialState;

    constructor(props) {
        super(props);

        this.saveEvt = new SaveSingle();
    }

    componentWillUnmount() {
        this.setState(initialState);

        this.props.data.rmSave(this.props.root_name, this.props.index);

        if(this.props.rmSave) {
            this.props.rmSave(this.props.data.id);
        }
    }

    //
    // Api Fetch and Push

    setBlock = (block) => {
        let title = false;
        if(block.schema && block.schema.title) {
            title = selectByDot(block.schema.title, this.props.data.data);
            if('string' === typeof title) {
                let tmp_title = document.createElement('DIV');
                tmp_title.innerHTML = title;
                title = tmp_title.textContent || tmp_title.innerText || "";

                if(50 < title.length) {
                    title = title.substr(0, 50) + '...';
                }
            }
        }

        this.setState({
            block,
            title: title,
            loaded: true,
            hasSchema: (!!block.schema)
        });

        this.props.data.addSave(this.props.root_name, this.props.index, this.saveEvt.trigger);
    };

    fetch(block) {
        const {loadBlock, cancelPromise} = this.props;

        this.setState({loaded: 'progress'});
        cancelPromise(loadBlock(block))
            .then((block) => {
                if(block) {
                    this.setBlock(block);
                } else {
                    this.setState({
                        loaded: 'error'
                    });
                }
            })
            .catch((err) => {
                if(!err.cancelled) {
                    if(err.waitForBlock) {
                        this.setState({waitingForLoading: true});
                    } else {
                        this.setState({
                            loaded: 'error'
                        });
                    }
                }
            });
    }

    componentDidUpdate(prevProps) {
        const {
            data,
            blocks, isBlockLoaded
        } = this.props;
        const {waitingForLoading} = this.state;

        if(data.id) {
            if(
                // when data is not the same
                prevProps.data !== data &&
                !waitingForLoading
            ) {
                data.rmSave(prevProps.root_name, prevProps.index);
                this.fetch(data.id);
            }

            if(
                // when block has been loaded and now is loaded
                waitingForLoading && true === isBlockLoaded(data.id)
            ) {
                data.rmSave(prevProps.root_name, prevProps.index);
                this.setState({waitingForLoading: false});
                this.setBlock(blocks[data.id]);
            }
        }
    }

    componentDidMount() {
        const {
            data,
            blocks, isBlockLoaded
        } = this.props;

        if(data.id) {
            if(
                // when block has been loaded already
                true === isBlockLoaded(data.id)
            ) {
                this.setBlock(blocks[data.id]);
            } else if(
                // when block is loading
                'progress' === isBlockLoaded(data.id)
            ) {
                this.setState({waitingForLoading: true});
            } else {
                this.fetch(this.props.data.id);
            }
        }
    }

    render() {
        const {data, t, theme, classes, head, deleteItem, onToggle, open} = this.props;
        const {addSave, rmSave} = this.saveEvt;
        const Hd = head;

        return (
            <React.Fragment>
                <Hd
                    icon={(p) => <MdWidgets size={'1.875em'} {...p}/>}
                    lbl={(p) => (
                        <React.Fragment>
                            {blockName(data.id, t)}
                            {this.state.title ?
                                /* todo: remove debug notice and fix no-string autosave */
                                <span
                                    style={{marginLeft: '3px', fontStyle: 'italic'}}
                                >· {'string' === typeof this.state.title ? this.state.title : <span style={{color: theme.textColorLight}}>title-no-string</span>}
                                </span> : null}
                        </React.Fragment>
                    )}
                    deleteItem={deleteItem}
                    onEdit={onToggle}
                    showEdit={this.state.hasSchema}
                    loading={'progress' === this.state.loaded}
                    isEditOpen={open}
                />

                <Wrapper className={classes.wrapper} withParent={false} pose={open ? 'visible' : 'hidden'}>

                    {('progress' === this.state.loaded || 'error' === this.state.loaded ?
                        <Loading
                            center={true}
                            errorWarning={'error' === this.state.loaded}
                        /> :
                        null)}

                    {this.state.block && this.state.block.schema ?
                        <SchemaEditor data={this.props.data.data}
                                      schema={this.state.block.schema}
                                      addSave={addSave}
                                      rmSave={rmSave}
                                      cacheid={this.props.uid}
                                      tScope={'doc-tree.block.' + data.id}
                        /> :
                        t('no-editable-meta')
                    }
                </Wrapper>
            </React.Fragment>
        )
    };
}

export default cancelPromise(storeBlock(withTheme(injectSheet(styling)(ContentBlock))));