import React from 'react';
import {MdDone} from 'react-icons/md';

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

import {ButtonSmall as Button} from '../../component/Form';
import DocTreeEditor from "../../component/DocTree/EditorLoader";

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

import {SaveSingle} from '../../component/ContentStore';
import {cancelPromise} from "../../component/cancelPromise";
import {storeBlock} from "./Stores/Block";
import {storePageType} from "./Stores/PageType";

const styling = theme => ({
    wrapper: {
        margin: '30px 0'
    },
    groups: {}
});

const initialState = {
    pageType: {},
    blockSelection: {},
    waitingForLoading: false,
    loaded: false
};

class ArticleDetailDocTree extends React.Component {

    state = initialState;

    constructor(props) {
        super(props);

        this.saveEvt = new SaveSingle();
    }

    componentWillUnmount() {
        this.setState(initialState);
    }

    //
    // Api Fetch and Push

    setLoaded(page_type, block_selection) {
        this.setState({
            pageType: page_type,
            blockSelection: block_selection,
            loaded: true
        });
    }

    fetch(pagetype) {
        const {
            cancelPromise,
            loadBlockList,
            loadPageType
        } = this.props;

        this.setState({loaded: 'progress'});

        cancelPromise(loadPageType(pagetype))
            .then((page_type) => {
                cancelPromise(loadBlockList())
                    .then((block_selection) => {
                        this.setLoaded(page_type, block_selection);
                    })
                    .catch((err) => {
                        if(err && !err.cancelled) {
                            if(err.waitForBlockList) {
                                this.setState({waitingForLoading: true});
                            } else {
                                this.setState({
                                    loaded: 'error'
                                });
                            }
                        }
                    });
            })
            .catch((err) => {
                if(err && !err.cancelled) {
                    if(err.waitForPageType) {
                        this.setState({waitingForLoading: true});
                    } else {
                        this.setState({
                            loaded: 'error'
                        });
                    }
                }
            });
    }

    trigger = () => {
        if(!this.props.saveFn) {
            console.error('ArticleDocTree: can not save, no prop `saveFn` binding exits.');
            return;
        }

        this.props.saveFn(this.saveEvt.trigger());
    };

    componentDidUpdate(prevProps) {
        const {waitingForLoading} = this.state;
        const {
            pageType, docTree,
            blockList, loadingBlockList,
            pageTypes, isPageTypeLoaded
        } = this.props;

        if(pageType) {
            if(
                prevProps.pageType !== pageType ||
                prevProps.docTree !== docTree
            ) {
                this.fetch(pageType);
            }
            if(
                // when block list AND page type has been loaded and now is loaded
                waitingForLoading && true === loadingBlockList && true === isPageTypeLoaded(pageType)
            ) {
                this.setState({waitingForLoading: false});
                this.setLoaded(pageTypes[pageType], blockList);
            }
        } else {
            console.error('ArticleDetailDocTree: pageType is not set on update.');
        }
    }

    componentDidMount() {
        const {
            pageType,
            blockList, loadingBlockList,
            pageTypes, isPageTypeLoaded
        } = this.props;

        if(pageType) {
            if(
                // when block list AND page type are already loaded
                true === loadingBlockList && true === isPageTypeLoaded(pageType)
            ) {
                this.setLoaded(pageTypes[pageType], blockList);
            } else if(
                // when block list OR page type are loading
                'progress' === loadingBlockList || 'progress' === isPageTypeLoaded(pageType)
            ) {
                this.setState({waitingForLoading: true});
            } else {
                // when need to load both
                this.fetch(this.props.pageType);
            }
        } else {
            console.error('ArticleDetailDocTree: pageType is not set on mount.');
        }
    }

    render() {
        const {t, classes, saving, theme} = this.props;
        const {addSave, rmSave} = this.saveEvt;

        return (
            <div className={classes.wrapper}>

                <h3 style={{width: '100%'}}>{t('doctree.title')}</h3>

                {('progress' === this.state.loaded || 'error' === this.state.loaded ?
                    <Loading
                        style={{
                            wrapper: {margin: 0},
                        }}
                        errorWarning={'error' === this.state.loaded}
                    /> :
                    null)}

                {true === this.state.loaded ?
                    <DocTreeEditor data={this.props.docTree}
                                   blockroot={this.state.pageType.block_root}
                                   blockSelection={this.state.blockSelection}
                                   addSave={addSave}
                                   rmSave={rmSave}
                    /> :
                    null}

                <Button onClick={this.trigger}>{t('doctree.save')} {('success' === saving ?
                    <MdDone/> : null)}</Button>

                {saving ?
                    ('progress' === saving || 'error' === saving ?
                        <React.Fragment>
                            <Loading style={{
                                wrapper: {margin: 0},
                                item: ('error' === saving ? {borderColor: theme.errorColor} : {}),
                            }}/>

                        </React.Fragment> : null)
                    : null}
            </div>
        )
    };
}

export default cancelPromise(storePageType(storeBlock(withTheme(injectSheet(styling)(ArticleDetailDocTree)))));