import React from 'react';
import {withNamespaces} from 'react-i18next';
import {MdEdit} from 'react-icons/md';
import {Redirect} from 'react-router-dom';

import Loading from "../../component/Loading";
import {withPusher} from "../../component/PushToApi/Pusher";

import {withTheme, injectSheet} from '../../lib/theme';
import {ApiRequest, DELETE, GET, PUT} from '../../lib/ApiRequest';
import i18n from "../../lib/i18n";
import ButtonInteractiveDelete from "../../component/ButtonInteractiveDelete";

import ProductDetailHead from './ProductDetailHead';
import ProductDetailLocaleSwitch from './ProductDetailLocaleSwitch';
import ProductDetailBaseEdit from './ProductDetailBaseEdit';
import ProductDetailLocaleBaseData from './ProductDetailLocaleBaseData';
import apiProduct from './ApiProduct';

const theming = theme => ({
    button: {
        fontSize: '0.875rem',
        background: 'none',
        padding: theme.gutter.base + 'px ' + theme.gutter.base * 2 + 'px',
        '&:first-child': {
            paddingLeft: 0,
        },
        '&:last-child': {
            paddingRight: 0,
        }
    },
    subTitle: {
        margin: 0
        //margin: '-12px 0 6px 0',
    }
});

const initialState = {
    productInfo: {},
    hasLocales: false,
    localeActive: false,
    localesPossible: [],
    locales: [],
    productTypesPossible: [],
    loaded: false,
    openBaseEdit: false,
    cacheid: false,
    moveToGroup: false,
    saving: {
        new_locale: false,
        delete: false,
        delete_locale: false,
        base_edit: false,
        update_locale: false,
    },
};

class ProductDetail extends React.Component {

    state = initialState;

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

    //
    // Api Fetch and Push

    createUpdatedSaving(name, val) {
        const saving = {...this.state.saving};
        saving[name] = val;
        return saving;
    }

    fetch(locale = false) {
        this.setState({loaded: 'progress'});
        (new ApiRequest('api', GET, 'shop/product/' + this.props.match.params.product))
            .debug(true)
            .header({})
            .exec()
            .then((res) => {
                if(res && res.data) {
                    if(res.data) {
                        let hasLocales = false;
                        let locales = [];
                        let localeActive = false;
                        let localesPossible = [];
                        let productTypesPossible = [];
                        if(res.data.locales) {
                            hasLocales = true;
                            locales = res.data.locales;
                            localeActive = locale ? locale : res.data.localeDefault;
                            localesPossible = res.data.localesPossible;
                            productTypesPossible = res.data.productTypesPossible;

                            if(-1 === locales.indexOf(localeActive) && locales[0]) {
                                localeActive = locales[0];
                            }
                        }

                        this.setState({
                            productInfo: res.data,
                            hasLocales,
                            locales,
                            localeActive,
                            localesPossible,
                            productTypesPossible,
                            loaded: true,
                            cacheid: '#' + this.props.match.params.product + '#'
                        });
                    }
                    if(res.data.error) {
                        this.setState({
                            loaded: 'error'
                        });
                    }
                } else {
                    this.setState({
                        loaded: 'error'
                    });
                }
            })
            .catch(() => {
                this.setState({
                    loaded: 'error'
                });
            });
    }

    pushDelete = () => {
        const endpoint = 'shop/product/' + this.props.match.params.product;

        this.props.addPushing(
            {
                name: 'pushDelete',
                context: endpoint,
                push: (resolve, reject) => {
                    this.setState({saving: this.createUpdatedSaving('delete', 'progress')});

                    (new ApiRequest('api', DELETE, endpoint))
                        .debug(true)
                        .header({})
                        .exec()
                        .then((res) => {
                            if(res && res.data) {
                                resolve(res.data);
                            } else {
                                reject();
                            }
                        })
                        .catch(() => {
                            reject();
                        });
                }
            })
            .then((data) => {
                if(data.error) {
                    this.setState({saving: this.createUpdatedSaving('delete', 'error')});
                    return;
                }

                this.setState({
                    saving: this.createUpdatedSaving('delete', 'success'),
                });

                apiProduct.triggerList();

                setTimeout(() => {
                    this.setState({saving: this.createUpdatedSaving('delete', false)});
                }, 4000);
            })
            .catch((data) => {
                if(!data.cancelled) {
                    this.setState({saving: this.createUpdatedSaving('delete', 'error')});
                }
            });
    };

    pushNewLocale = () => {
        const {localeActive} = this.state;

        const endpoint = 'shop/product/' + this.props.match.params.product + '/locale/' + localeActive;

        this.props.addPushing(
            {
                name: 'pushNewLocale',
                context: endpoint,
                push: (resolve, reject) => {
                    this.setState({saving: this.createUpdatedSaving('new_locale', 'progress')});

                    (new ApiRequest('api', PUT, endpoint))
                        .debug(true)
                        .header({})
                        .exec()
                        .then((res) => {
                            if(res && res.data) {
                                resolve(res.data);
                            } else {
                                reject();
                            }
                        })
                        .catch(() => {
                            reject();
                        });
                }
            })
            .then((data) => {
                if(data.error) {
                    this.setState({saving: this.createUpdatedSaving('new_locale', 'error')});
                    return;
                }

                this.setState({
                    saving: this.createUpdatedSaving('new_locale', 'success'),
                });
                this.fetch(localeActive);

                setTimeout(() => {
                    this.setState({saving: this.createUpdatedSaving('new_locale', false)});
                }, 4000);
            })
            .catch((data) => {
                if(!data.cancelled) {
                    this.setState({saving: this.createUpdatedSaving('new_locale', 'error')});
                }
            });
    };

    pushDeleteLocale = () => {
        const {localeActive, productInfo} = this.state;

        const endpoint = 'shop/product-data/' + productInfo.data[localeActive].id;

        this.props.addPushing(
            {
                name: 'pushDeleteLocale',
                context: endpoint,
                push: (resolve, reject) => {
                    this.setState({saving: this.createUpdatedSaving('delete_locale', 'progress')});

                    (new ApiRequest('api', DELETE, endpoint))
                        .debug(true)
                        .header({})
                        .exec()
                        .then((res) => {
                            if(res && res.data) {
                                resolve(res.data);
                            } else {
                                reject();
                            }
                        })
                        .catch(() => {
                            reject();
                        });
                }
            })
            .then((data) => {
                if(data.error) {
                    this.setState({saving: this.createUpdatedSaving('delete_locale', 'error')});
                    return;
                }

                this.setState({
                    saving: this.createUpdatedSaving('delete_locale', 'success'),
                });
                this.fetch(localeActive);

                setTimeout(() => {
                    this.setState({saving: this.createUpdatedSaving('delete_locale', false)});
                }, 4000);
            })
            .catch((data) => {
                if(!data.cancelled) {
                    this.setState({saving: this.createUpdatedSaving('delete_locale', 'error')});
                }
            });
    };

    pushBaseData = (name, productType = false, group = false) => {
        const {localeActive, productInfo} = this.state;

        const endpoint = 'shop/product/' + this.props.match.params.product;

        const moveToGroup = (group && productInfo.group !== group);

        const data = {
            name,
        };
        if(group) {
            data.group = group
        }
        if(productType) {
            data.product_type = productType;
        }

        this.props.addPushing(
            {
                name: 'pushBaseData',
                context: endpoint,
                push: (resolve, reject) => {
                    this.setState({saving: this.createUpdatedSaving('base_edit', 'progress')});
                    (new ApiRequest('api', PUT, endpoint, data))
                        .debug(true)
                        .header({})
                        .exec()
                        .then((res) => {
                            if(res && res.data) {
                                resolve(res.data);
                            } else {
                                reject();
                            }
                        })
                        .catch(() => {
                            reject();
                        });
                }
            })
            .then((data) => {
                if(data.error) {
                    this.setState({saving: this.createUpdatedSaving('base_edit', 'error')});
                    return;
                }

                this.setState({
                    saving: this.createUpdatedSaving('base_edit', 'success'),
                    openBaseEdit: false
                });
                if(moveToGroup) {
                    this.setState({
                        moveToGroup: group,
                    });
                    setTimeout(() => {
                        this.setState({
                            moveToGroup: false,
                        })
                    }, 0);
                } else {
                    this.fetch(localeActive);
                }

                setTimeout(() => {
                    this.setState({saving: this.createUpdatedSaving('base_edit', false)});
                }, 4000);
            })
            .catch((data) => {
                if(!data.cancelled) {
                    this.setState({saving: this.createUpdatedSaving('base_edit', 'error')});
                }
            });
    };

    pushDataLocale = (productData) => {
        const {productInfo, localeActive} = this.state;

        const endpoint = 'shop/product-data/' + productInfo.data[localeActive].id;

        const product_data = {...productData};

        const itmInf = {...productInfo};
        const itmInfData = {...itmInf.data};
        itmInfData[localeActive] = product_data;
        itmInf.data = itmInfData;
        this.setState({productInfo: itmInf});

        this.props.addPushing(
            {
                name: 'pushproductDataLocale',
                context: endpoint,
                push: (resolve, reject) => {
                    this.setState({saving: this.createUpdatedSaving('update_locale', 'progress')});

                    (new ApiRequest('api', PUT, endpoint, product_data))
                        .debug(true)
                        .header({})
                        .exec()
                        .then((res) => {
                            if(res && res.data) {
                                resolve(res.data);
                            } else {
                                reject();
                            }
                        })
                        .catch(() => {
                            reject();
                        });
                }
            })
            .then((data) => {
                if(data.error) {
                    this.setState({saving: this.createUpdatedSaving('update_locale', 'error')});
                    return;
                }

                this.setState({saving: this.createUpdatedSaving('update_locale', 'success')});

                setTimeout(() => {
                    this.setState({saving: this.createUpdatedSaving('update_locale', false)});
                }, 4000);
            })
            .catch((data) => {
                if(!data.cancelled) {
                    this.setState({saving: this.createUpdatedSaving('update_locale', 'error')});
                }
            });
    };

    //
    // Open Toggles

    openBaseEdit = () => {
        this.setState({
            openBaseEdit: !this.state.openBaseEdit
        });
    };

    //
    // Default Lifecycles

    shouldComponentUpdate(nextProps, nextState) {

        return true;
    }

    componentDidUpdate(prevProps) {
        if(prevProps.match.params.group !== this.props.match.params.group ||
            prevProps.match.params.product !== this.props.match.params.product) {
            this.fetch();
        }
    }

    componentDidMount() {
        this.fetch();
    }

    localeSwitch = (locale) => {
        if(locale !== this.state.localeActive) {
            this.setState({
                localeActive: locale
            })
        }
    };

    render() {
        const {t, theme, classes} = this.props;
        const {
            hasLocales, locales, localeActive, localesPossible,
            productTypesPossible,
            productInfo
        } = this.state;

        /**
         * If the locale exists in the locales of the product
         * @var {boolean} activeLocaleExists
         */
        const activeLocaleExists = (hasLocales && locales && -1 !== locales.indexOf(localeActive));
        /**
         * If the locale is valid as a locale (e.g. activeLocale is not allowed from API but somehow was submitted from API)
         * @var {boolean} activeLocalePossible
         */
        const activeLocalePossible = (hasLocales && localesPossible && -1 !== localesPossible.indexOf(localeActive));
        /**
         * Hold only the product information for the active locale
         */
        const productData = activeLocaleExists ? productInfo.data[localeActive] : {};

        return (
            <React.Fragment>
                {
                    (
                        this.state.moveToGroup &&
                        this.props.match.params.group !== this.state.moveToGroup
                    ) ? <Redirect to={'/' + i18n.languages[0] + '/shop/objects/' + this.state.moveToGroup + '/' + this.props.match.params.product}/>
                        : null
                }
                {
                    (
                        'success' === this.state.saving.delete
                    ) ? <Redirect to={'/' + i18n.languages[0] + '/shop/objects/' + this.props.match.params.group}/>
                        : null
                }

                {true !== this.state.loaded ? <h1>{t('title')}</h1> : null}
                {
                    true === this.state.loaded ?
                        (
                            <React.Fragment>
                                <div className={classes.wrapperHead}>
                                    <h1>{t('title')}</h1>
                                    {productInfo && productInfo.id ?
                                        <div style={{display: 'flex', alignproducts: 'center', margin: theme.gutter.base * -4 + 'px 0 ' + theme.gutter.base * 2 + 'px 0'}}>
                                            <h2 className={classes.subTitle}>{productInfo.name}</h2>


                                            <React.Fragment>
                                                <button onClick={this.openBaseEdit}
                                                        style={{marginLeft: theme.gutter.base + 'px'}}
                                                ><MdEdit color={theme.textColor} size={'1em'}/></button>

                                                <ButtonInteractiveDelete onClick={this.pushDelete}
                                                                         style={{
                                                                             fontSize: '0.875rem',
                                                                             color: theme.textColor,
                                                                             marginLeft: 'auto',
                                                                             display: 'flex',
                                                                             alignproducts: 'center'
                                                                         }}
                                                ><span style={{marginRight: theme.gutter.base + 'px'}}>{t('btn-delete-product')}</span></ButtonInteractiveDelete>

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

                                    <ProductDetailBaseEdit
                                        localesPossible={localesPossible}
                                        productInfo={productInfo}
                                        productData={productData}
                                        pushBaseData={this.pushBaseData}
                                        open={this.state.openBaseEdit}
                                        saving={this.state.saving.base_edit}
                                    />

                                    <ProductDetailLocaleSwitch
                                        localesPossible={localesPossible}
                                        locales={locales}
                                        localeActive={localeActive}
                                        localeSwitch={this.localeSwitch}
                                    />

                                    <ProductDetailHead
                                        data={productData}
                                        localesPossible={localesPossible}
                                        localeActive={localeActive}
                                        productTypesPossible={productTypesPossible}
                                        pushNewLocale={this.pushNewLocale}
                                        pushDeleteLocale={this.pushDeleteLocale}
                                        activeLocalePossible={activeLocalePossible}
                                        activeLocaleExists={activeLocaleExists}
                                        savingDelete={this.state.saving.delete_locale}
                                        savingNew={this.state.saving.new_locale}
                                    />

                                    {activeLocaleExists ?
                                        productData && productInfo.product_type_data ?
                                            <ProductDetailLocaleBaseData productData={productData}
                                                                      localeActive={localeActive}
                                                                      schema={productInfo.product_type_data.schema}
                                                                      saveFn={this.pushDataLocale}
                                                                      saving={this.state.saving.update_locale}
                                                                      cacheid={this.state.cacheid}
                                            /> :
                                            <React.Fragment>
                                                (<p>{t('product-data-error')} {!productData ? t('product-data-error--no-data') : null} {!productInfo.product_type_data ? t('product-data-error--no-product-type-data') : null}</p>)
                                            </React.Fragment>
                                        : null}
                                </div>

                            </React.Fragment>
                        ) :
                        ('progress' === this.state.loaded || 'error' === this.state.loaded ?
                            <Loading style={{
                                wrapper: {margin: 0},
                                item: ('error' === this.state.loaded ? {borderColor: this.props.theme.errorColor} : {}),
                            }}/> :
                            null)
                }
            </React.Fragment>
        )
    };
}

export default withNamespaces('page--shop-product')(withPusher(withTheme(injectSheet(theming)(ProductDetail))));