import React from 'react';
import {withContextConsumer} from "@formanta/react";
import {ApiRequest, DELETE, GET, POST, PUT} from "../../../lib/ApiRequest";
import {isUndefined} from "@formanta/js";
import {Pushing, withPusher} from '../../../component/Pusher/Pusher';
import {cancelPromise} from "../../../component/cancelPromise";
import {withApiControl} from "../../../component/ApiControl";

const StoreProductContext = React.createContext({});

class StoreProductProviderBase extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            products: {},
            loadingProducts: {},
            createProduct: this.createProduct,
            createProductLocale: this.createProductLocale,
            deleteProduct: this.deleteProduct,
            deleteProductLocale: this.deleteProductLocale,
            loadProduct: this.loadProduct,
            loadProductList: this.loadProductList,
            isProductListLoaded: this.isProductListLoaded,
            updateProductBaseData: this.updateProductBaseData,
            updateProductLocaleData: this.updateProductLocaleData,
        };
    }

    doApiRequest(type, endpoint, name, data = {}) {
        return new Pushing(
            name,
            endpoint,
            (resolve, reject) => {
                (new ApiRequest('api', type, endpoint, data))
                    .debug(true)
                    .header({})
                    .exec()
                    .then((res) => {
                        if(res && res.data) {
                            if(res.data.error) {
                                return Promise.reject(res);
                            }
                            resolve(res.data);
                        } else {
                            reject();
                        }
                    })
                    .catch((err) => {
                        this.props.handleApiFail(err, name);
                        reject(err);
                    });
            }
        )
    }

    isProductListLoaded = (group) => {
        if(isUndefined(this.state.loadingProducts[group])) {
            return false;
        }
        return this.state.loadingProducts[group];
    };

    updateProductListLoaded = (group, status) => {
        const loadingProducts = {...this.state.loadingProducts};
        loadingProducts[group] = status;
        this.setState({loadingProducts});
    };

    loadProduct = (product) => {
        return (new ApiRequest('api', GET, 'shop/product/' + product))
            .debug(true)
            .header({})
            .exec()
            .then((res) => {
                if(res && res.data) {
                    if(res.data.error) {
                        return Promise.reject(res);
                    }
                    return res.data;
                } else {
                    return Promise.reject(res);
                }
            })
            .catch((err) => {
                this.props.handleApiFail(err, 'loadProduct');
                return Promise.reject(err);
            });
    };

    // is implemented
    loadProductList = (group, forceLoad = false) => {
        const {cancelPromise} = this.props;
        if(isUndefined(this.state.products[group]) || forceLoad) {

            this.updateProductListLoaded(group, 'progress');
            cancelPromise(new ApiRequest('api', GET, 'shop/group/' + group + '/product').debug(true)
                .exec())
                .then((res) => {
                    if(res && res.data && !res.data.error) {
                        const products = {...this.state.products};
                        products[group] = res.data;

                        this.setState({
                            products,
                        });
                        this.updateProductListLoaded(group, true);
                    } else {
                        this.updateProductListLoaded(group, 'error');
                    }
                })
                .catch((err) => {
                    this.props.handleApiFail(err, 'loadProductList');
                    if(err && !err.cancelled) {
                        this.updateProductListLoaded(group, 'error');
                    }
                });
        }
    };

    createProduct = (group, name, product_type) => {
        const endpoint = 'shop/product';

        const {execPushing} = this.props;

        const data = {
            name,
            product_type,
            group
        };

        return execPushing(
            this.doApiRequest(POST, endpoint, 'createProduct', data)
        ).then((data) => {
            this.loadProductList(group, true);
            return data;
        });
    };

    createProductLocale = (product, locale) => {
        const endpoint = 'shop/product/' + product + '/locale/' + locale;

        const {execPushing} = this.props;

        return execPushing(
            this.doApiRequest(PUT, endpoint, 'createProductLocale')
        );
    };

    deleteProduct = (group, product) => {
        const endpoint = 'shop/product/' + product;

        const {execPushing} = this.props;

        return execPushing(
            this.doApiRequest(DELETE, endpoint, 'deleteProduct')
        ).then((data) => {
            this.loadProductList(group, true);
            return data;
        });
    };

    deleteProductLocale = (product, localeActive) => {
        const endpoint = 'shop/product-data/' + localeActive;
        const {execPushing} = this.props;

        return execPushing(
            this.doApiRequest(DELETE, endpoint, 'deleteProductLocale')
        );
    };

    updateProductBaseData = (group, product, data) => {
        const {execPushing} = this.props;
        const endpoint = 'shop/product/' + product;

        return execPushing(
            this.doApiRequest(PUT, endpoint, 'updateProductBaseData', data)
        ).then((data) => {
            this.loadProductList(group, true);
            return data;
        });
    };

    updateProductLocaleData = (product_data_id, data) => {
        const {execPushing} = this.props;
        const endpoint = 'shop/product-data/' + product_data_id;

        return execPushing(
            this.doApiRequest(PUT, endpoint, 'updateProductLocaleData', data)
        );
    };

    render() {
        return (
            <StoreProductContext.Provider value={this.state}>
                {this.props.children}
            </StoreProductContext.Provider>
        );
    }
}

const storeProduct = withContextConsumer(StoreProductContext.Consumer);

const StoreProductProvider = cancelPromise(withApiControl(withPusher(StoreProductProviderBase)));

export {StoreProductProvider, storeProduct};