import React, {PureComponent} from 'react';
import PropTypes from "prop-types";
import {FilterOptions} from "./options/utils";
import {v4 as uuidv4} from "uuid";
import {DragDropContext} from "@hello-pangea/dnd";

import {copy, itemsUnfoldedList, nbrOccupiedSlotsInCrate, remove, reorder} from "./utils";

import {Layout} from "./Layout.jsx";
import {Backlog} from "./Backlog.jsx";
import {OrderPanel} from "./OrderPanel.jsx";
import {CrateMode} from "./CrateMode.jsx";
import {Crate} from "./Crate.jsx";
import {Cart} from "./Cart.jsx";
import {OrderSummary} from "./OrderSummary.jsx";
import {OrderForm} from "./OrderForm.jsx";

/**
 * Component that render the entire shop
 */

export class Shop extends PureComponent {

    static get propTypes() {
        return {
            data: PropTypes.object.isRequired,
        };
    }

    constructor(props) {
        super(props);
        this.state = this.props.data;
        this.handleCrateModeChange = this.handleCrateModeChange.bind(this);
        this.handleOnDragEnd = this.handleOnDragEnd.bind(this);
        this.handleDeleteItem = this.handleDeleteItem.bind(this);
        this.handleDeleteAllItems = this.handleDeleteAllItems.bind(this);
        this.handleMouseEnterItem = this.handleMouseEnterItem.bind(this);
        this.handleMouseLeaveItem = this.handleMouseLeaveItem.bind(this);
        this.handleClickAddItem = this.handleClickAddItem.bind(this);
        this.checkAlerts = this.checkAlerts.bind(this);
        this.handleClickSelectItem = this.handleClickSelectItem.bind(this);
        this.handleClickSubmit = this.handleClickSubmit.bind(this);
        this.handleToggleOverlayRemove = this.handleToggleOverlayRemove.bind(this);
        this.handleShowOverlayRemove = this.handleShowOverlayRemove.bind(this);
        this.handleClickToggleMobileSideMenu = this.handleClickToggleMobileSideMenu.bind(this);
        this.handleClickCloseRFQFeedback = this.handleClickCloseRFQFeedback.bind(this);
        this.handleClickShowOrder = this.handleClickShowOrder.bind(this);
        this.handleClickOpenImport = this.handleClickOpenImport.bind(this);
        this.handleLoadCustomConf = this.handleLoadCustomConf.bind(this);
        this.handleCardsUpdated = this.handleCardsUpdated.bind(this);

        this.timer = null;
        this.timer_remove = null;
    }

    componentDidMount() {
        const source = {
            droppableId: 'backlog',
            indexes: [
                itemsUnfoldedList.findIndex(element => element === "eem_pwr_mod"),
                itemsUnfoldedList.findIndex(element => element === "kasli")
            ],
        };
        const destination = {
            droppableId: 'cart',
            index: 0,
        };

        this.handleOnDragEnd({
            source,
            destination
        });
    }

    componentDidUpdate(prevProps, prevState) {
        /**
         * We check alerts (reminder + warning) only when items inside crate or
         * crate mode change.
         *
         * In the function checkAlerts, we DO NOT want to change items as we will
         * trigger again this function (componentDidUpdate) and thus,
         * making an infinite loop.
         */
        if (
            (prevState.columns.cart.items !== this.state.columns.cart.items) ||
            (prevState.currentMode !== this.state.currentMode)
        ) {
            this.checkAlerts(this.state.columns.cart.items);
        }

        if (this.state.newCardJustAdded) {
            this.timer = setTimeout(() => {
                this.setState({
                    newCardJustAdded: false,
                });
            }, 2000);
        }
    }

    componentWillUnmount() {
        clearTimeout(this.timer);
    }

    handleCardsUpdated() {
        this.checkAlerts(this.state.columns.cart.items);
    }

    handleCrateModeChange(mode) {
        this.setState({
            currentMode: mode,
        });
    }

    handleDeleteItem(index) {
        let cloned = Array.from(this.state.columns.cart.items);
        let cloned_data = Array.from(this.state.columns.cart.itemsData);
        cloned.splice(index, 1);
        cloned_data.splice(index, 1);

        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    items: cloned,
                    itemsData: cloned_data,
                },
            },
        });
    }

    handleDeleteAllItems() {
        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    items: [],
                    itemsData: []
                },
            },
        });
    }

    handleMouseEnterItem(id) {
        this.setState({
            ...this.state,
            currentItemHovered: id,
        });
    }

    handleMouseLeaveItem() {
        this.setState({
            ...this.state,
            currentItemHovered: null,
        });
    }

    handleClickAddItem(index, tap) {
        const source = {
            droppableId: 'backlog',
            index: index,
        };
        const destination = {
            droppableId: 'cart',
            index: this.state.columns.cart.items.length,
        };

        this.handleOnDragEnd({
            source,
            destination
        }, tap);
    }

    handleClickSelectItem(index) {
        const itemsCloned = Array.from(this.state.columns.cart.items);

        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    items: itemsCloned.map((item, id) => {
                        return {...item, selected: id === index ? true : false};
                    }),
                }
            },
        });
    }

    handleToggleOverlayRemove(index, show) {
        const itemsCloned = Array.from(this.state.columns.cart.items);

        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    items: itemsCloned.map((item, id) => {
                        return {
                            ...item,
                            showOverlayRemove: id === index ? show : false
                        };
                    }),
                }
            },
        });
    }

    handleShowOverlayRemove(index) {
        if (this.timer_remove)
            clearTimeout(this.timer_remove);

        this.handleToggleOverlayRemove(index, true);

        this.timer_remove = setTimeout(() => {
            this.handleToggleOverlayRemove(index, false);
        }, 2000);
    }

    handleClickShowOrder() {
        const crate = {
            items: [],
            type: this.state.currentMode,
        };
        const clonedCart = Array.from(this.state.columns.cart.items);
        const clonedCartData = Array.from(this.state.columns.cart.itemsData);
        for (const i in clonedCart) {
            const item = clonedCart[i];
            const item_data = clonedCartData[i];
            crate.items.push({
                'pn': item.name_number,
                'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null,
            });
        }

        this.setState({
            isProcessing: false,
            shouldShowRFQFeedback: true,
            RFQBodyType: 'show',
            RFQBodyOrder: JSON.stringify(crate, null, 2),
        });
    }

    handleClickOpenImport() {
        this.setState({
            isProcessing: false,
            shouldShowRFQFeedback: true,
            RFQBodyType: 'import',
        });
    }

    handleLoadCustomConf(customconf) {
        if (!customconf) {return; }

        const items = this.props.data.items;

        let new_items = [];
        let new_items_data = [];


        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    items: [],
                },
            },
        }, function () {

            customconf.items.map(function (item) {
                Object.keys(items).map(key => {
                    if (item.pn && item.pn === items[key].name_number) {
                        new_items.push(Object.assign({
                            ...items[key],
                        }, {
                            id: uuidv4(),
                            options_data: item.options ? item.options : null,
                        }));
                        new_items_data.push({options_data: item.options ? item.options : null});
                    }
                });

                return item;
            });

            this.setState({
                ...this.state,
                columns: {
                    ...this.state.columns,
                    cart: {
                        ...this.state.columns.cart,
                        items: new_items,
                        itemsData: new_items_data,
                    },
                },
                currentMode: customconf.type,
            });
        });
    }

    handleClickSubmit(note, email) {
        const crate = {
            items: [],
            type: this.state.currentMode,
        };
        const clonedCart = Array.from(this.state.columns.cart.items);
        const clonedCartData = Array.from(this.state.columns.cart.itemsData);
        for (const i in clonedCart) {
            const item = clonedCart[i];
            const item_data = clonedCartData[i];
            crate.items.push({
                'pn': item.name_number,
                'options': (item_data.options_data && item_data.options) ? FilterOptions(item_data.options, item_data.options_data) : null,
            });
        }

        const {data} = this.props;

        this.setState({isProcessing: true});

        fetch(data.API_RFQ, {
            method: "POST",
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({
                email,
                note,
                configuration: JSON.stringify(crate)
            })
        }).then(response => {
            if (response.status !== 200) {
                throw Error("Response status is not OK: " + response.status + ".\n" + response);
            }
            this.setState({
                isProcessing: false,
                shouldShowRFQFeedback: true,
                RFQBodyType: 'email',
                isProcessingComplete: true,
            });
        }).catch(err => {
            console.error("Request failed, reason:", err)
            this.setState({isProcessing: false}, () => {
                alert("We cannot receive your request. Try using the export by coping the configuration and send it to us at sales@m-labs.hk");
            });
        })
    }

    handleOnDragEnd(result, newAdded) {
        const {
            source,
            destination,
        } = result;
        let dragged_items = [];
        if (source.indexes) {
            source.indexes.forEach((card_index, _) => {
                dragged_items.push(itemsUnfoldedList[card_index]);
            })
        } else if (source.index >= 0) {
            dragged_items.push(itemsUnfoldedList[source.index]);
        }


        if (!destination) {
            if (source.droppableId === 'cart') {
                this.setState({
                    ...this.state,
                    newCardJustAdded: false,
                    columns: {
                        ...this.state.columns,
                        [source.droppableId]: {
                            ...this.state.columns[source.droppableId],
                            items: remove(
                                this.state.columns[source.droppableId].items,
                                source.index,
                            ),
                            itemsData: remove(
                                this.state.columns[source.droppableId].itemsData,
                                source.index,
                            )
                        },
                    },
                });
            }

            return;
        }

        switch(source.droppableId) {

            case 'backlog':
                if (source.droppableId !== destination.droppableId) {
                    this.setState({
                        ...this.state,
                        newCardJustAdded: newAdded ? true : false,
                        columns: {
                            ...this.state.columns,
                            [destination.droppableId]: {
                                ...this.state.columns[destination.droppableId],
                                items: copy(
                                    this.state.items,
                                    this.state.columns[source.droppableId],
                                    this.state.columns[destination.droppableId],
                                    dragged_items,
                                    destination,
                                ),
                            },
                        },
                    });
                }
                break;

            case destination.droppableId:
                this.setState({
                    ...this.state,
                    newCardJustAdded: false,
                    columns: {
                        ...this.state.columns,
                        [destination.droppableId]: {
                            ...this.state.columns[destination.droppableId],
                            items: reorder(
                                this.state.columns[destination.droppableId].items,
                                source.index,
                                destination.index,
                            ),
                            itemsData: reorder(
                                this.state.columns[destination.droppableId].itemsData,
                                source.index,
                                destination.index,
                            ),
                        },
                    },
                });
                break;

            default:
                break;
        }
    }

    handleClickToggleMobileSideMenu() {
        this.setState({
            ...this.state,
            mobileSideMenuShouldOpen: !this.state.mobileSideMenuShouldOpen,
        });
    }

    handleClickCloseRFQFeedback() {
        this.setState({
            shouldShowRFQFeedback: false,
        });
    }

    checkAlerts(newItems) {
        console.log('--- START CHECKING CRATE WARNING ---');

        const {
            currentMode,
            crateModeSlots,
            crateRules,
        } = this.state;

        const itemsCloned = Array.from(newItems);
        const itemsData = [];
        const rules = {};

        itemsCloned.forEach((elem, idx) => {
            if (!(idx in itemsData)) itemsData[idx] = elem;
            if (idx in this.state.columns.cart.itemsData && this.state.columns.cart.itemsData[idx].options_data) {
                itemsCloned[idx].options_data = this.state.columns.cart.itemsData[idx].options_data;
            }
            itemsData[idx].warnings = {};
        });


        // check number of slot in crate
        const nbrOccupied = nbrOccupiedSlotsInCrate(newItems);
        if (nbrOccupied > crateModeSlots[currentMode]) {
            rules[crateRules.maxSlot.type] = {...crateRules.maxSlot};
        } else if (crateModeSlots[currentMode] === 21 && nbrOccupied <= 10) {
            rules[crateRules.compactSlot.type] = {...crateRules.compactSlot};
        }


        // check the number of EEM connectors available for all Kasli
        const idxK = itemsCloned.reduce((prev, next, i) => {
            if (next.type === 'kasli' || next.type === 'vhdcicarrier') {
                prev.push(i);
            }
            return prev;
        }, []);
        for (let i = 0; i <= idxK.length - 1; i++) {
            let slots;
            let nbUsedSlot = 0;
            let nbrCurrentClock = 0;
            let idx = idxK[i];

            if (i !== idxK.length - 1) {
                slots = itemsCloned.slice(idx + 1, idxK[i + 1]);
            } else {
                slots = itemsCloned.slice(idx + 1);
            }

            if (i == 0) {
                const slots_need_resource = itemsCloned.slice(0, idx);
                const idx_need = slots_need_resource.findIndex(e => (e.rules && e.rules.resources));

                if (idx_need != -1) {
                    if (idx_need in itemsData) {
                        if ('warnings' in itemsData[idx_need]) {
                            itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                        } else {
                            itemsData[idx_need].warnings = {};
                            itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                        }
                    } else {
                        itemsData[idx_need] = {...itemsCloned[idx_need]};
                        itemsData[idx_need].warnings = {};
                        itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                    }
                }
            }

            const process_slots = (item) => {
                if (!item.options_data
                    || item.options_data.ext_pwr === false
                    || item.options_data.mono_eem === false
                )
                    return item.slotOccupied;
                else if (item.options_data.ext_pwr === true)
                    return 0;
                else if (item.options_data.mono_eem === true || item.options_data.n_eem === "1 EEM")
                    return 1;
                else if (item.options_data.n_eem === "3 EEM")
                    return 3;

                return item.slotOccupied;
            }

            nbUsedSlot = slots
                .filter(item => item.type !== 'idc-bnc')
                .reduce((prev, next) => {
                    return prev + process_slots(next);
                }, 0);

            nbrCurrentClock = slots
                .reduce((prev, next) => {
                    return next.type === 'clocker' ? prev + ((next.options_data && next.options_data.ext_clk === true) ? 0 : next.clockOccupied) : prev;
                }, 0);

            if (idx in itemsData) {
                itemsData[idx].nbrCurrentSlot = nbUsedSlot;
                itemsData[idx].nbrCurrentClock = nbrCurrentClock;
                if (!('warnings' in itemsData[idx])) {
                    itemsData[idx].warnings = {};
                }
            } else {
                itemsData[idx] = {...itemsCloned[idx]};
                itemsData[idx].nbrCurrentSlot = nbUsedSlot;
                itemsData[idx].nbrCurrentClock = nbrCurrentClock;
                itemsData[idx].warnings = {};
            }

            if (nbUsedSlot > itemsCloned[idx].nbrSlotMax) {
                if (itemsCloned[idx].rules.maxSlot.message) {
                    rules[itemsCloned[idx].rules.maxSlot.type] = {...itemsCloned[idx].rules.maxSlot};
                }
                itemsData[idx].warnings.maxSlotWarning = {...itemsCloned[idx].rules.maxSlotWarning};
            }

            if (nbrCurrentClock > itemsCloned[idx].nbrClockMax) {
                rules[itemsCloned[idx].rules.maxClock.type] = {...itemsCloned[idx].rules.maxClock};
                itemsData[idx].warnings.maxClockWarning = {...itemsCloned[idx].rules.maxClockWarning};
            }

            if (itemsCloned.length > (idx + 1)) {
                const ddkali = itemsCloned[idx + 1];
                if (ddkali.type === 'kasli' || ddkali.type === 'vhdcicarrier') {
                    rules[ddkali.rules.follow.type] = {...ddkali.rules.follow};
                }
            }
        }

        if (idxK.length === 0) {
            const slots_need_resource = itemsCloned.slice(0);
            const idx_need = slots_need_resource.findIndex(e => (e.rules && e.rules.resources));

            if (idx_need != -1) {
                if (idx_need in itemsData) {
                    if ('warnings' in itemsData[idx_need]) {
                        itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                    } else {
                        itemsData[idx_need].warnings = {};
                        itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                    }
                } else {
                    itemsData[idx_need] = {...itemsCloned[idx_need]};
                    itemsData[idx_need].warnings = {};
                    itemsData[idx_need].warnings.resources = {...itemsCloned[idx_need].rules.resources};
                }
            }
        }


        // check number of clock connector available
        const idxC = itemsCloned.reduce((prev, next, i) => {
            if (next.type === 'kasli' || next.type === 'clocker') {
                prev.push(i);
            }
            return prev;
        }, []);
        for (let i = 0; i <= idxC.length - 1; i++) {
            let slots;
            let nbrCurrentClock = 0;
            let idx = idxC[i];

            if (i !== idxC.length - 1) {
                slots = itemsCloned.slice(idx + 1, idxC[i + 1]);
            } else {
                slots = itemsCloned.slice(idx + 1);
            }

            nbrCurrentClock = slots.reduce((prev, next) => {
                return prev + ((next.options_data && next.options_data.ext_clk && next.options_data.ext_clk.checked) ? 0 : next.clockOccupied);
            }, 0);

            if (idx in itemsData) {
                if (itemsData[idx].nbrCurrentClock && itemsData[idx].type !== "clocker") {
                    itemsData[idx].nbrCurrentClock += nbrCurrentClock;
                } else {
                    itemsData[idx].nbrCurrentClock = nbrCurrentClock;
                }
            } else {
                itemsData[idx] = {...itemsCloned[idx]};
                itemsData[idx].nbrCurrentClock = nbrCurrentClock;
                itemsData[idx].warnings = {};
            }

            if (nbrCurrentClock > itemsCloned[idx].nbrClockMax) {
                rules[itemsCloned[idx].rules.maxClock.type] = {...itemsCloned[idx].rules.maxClock};
                itemsData[idx].warnings.maxClockWarning = {...itemsCloned[idx].rules.maxClockWarning};
            }
        }


        if (itemsCloned.find(elem => elem.type === 'urukul')) {
            if (this.state.items['urukul'].rules.info) {
                rules[this.state.items['urukul'].rules.info.type] = {...this.state.items['urukul'].rules.info};
            }
        }


        // check if IDC-BNC is correctly positionned (after Zotino or HD68)
        const idxIDCBNC = itemsCloned.reduce((prev, next, i) => {
            if (next.type === 'idc-bnc') {
                prev.push(i);
            }
            return prev;
        }, []);
        for (var i = idxIDCBNC.length - 1; i >= 0; i--) {
            const ce = idxIDCBNC[i];
            let shouldWarning = false;

            if (ce == 0) {
                shouldWarning = true;
            } else if (ce >= 1) {
                const pe = idxIDCBNC[i] - 1;
                if (itemsCloned[pe].type !== 'zotino' &&
                    itemsCloned[pe].type !== 'hd68' &&
                    itemsCloned[pe].type !== 'idc-bnc') {
                    shouldWarning = true;
                }
            }

            if (shouldWarning) {
                itemsData[ce] = {...itemsCloned[ce]};
                itemsData[ce].warnings = {};
                itemsData[ce].warnings.wrong = {...itemsCloned[ce].rules.wrong};
            }
        }


        // check number of IDC-BNC adapters for a Zotino and HD68-IDC
        const idxZH = itemsCloned.reduce((prev, next, i) => {
            if (next.type === 'zotino' || next.type === 'hd68') {
                prev.push(i);
            }
            return prev;
        }, []);
        for (let i = 0; i <= idxZH.length - 1; i++) {
            let slots;
            let nbUsedSlot = 0;
            let idx = idxZH[i];

            if (i !== idxZH.length - 1) {
                slots = itemsCloned.slice(idx + 1, idxZH[i + 1]);
            } else {
                slots = itemsCloned.slice(idx + 1);
            }

            let stopCount = false;
            nbUsedSlot = slots.reduce((prev, next, ci, ca) => {
                if (ci === 0 && next.type === 'idc-bnc') {
                    return prev + 1;
                } else if (ca[0].type === 'idc-bnc' && ci > 0 && ca[ci - 1].type === 'idc-bnc') {
                    if (next.type !== 'idc-bnc') { stopCount = true; }
                    return prev + (next.type === 'idc-bnc' && !stopCount ? 1 : 0);
                }
                return prev;
            }, 0);

            if (idx in itemsData) {
                itemsData[idx].nbrCurrentSlot = nbUsedSlot;
                if (!('warnings' in itemsData[idx])) {
                    itemsData[idx].warnings = {};
                }
            } else {
                itemsData[idx] = {...itemsCloned[idx]};
                itemsData[idx].nbrCurrentSlot = nbUsedSlot;
                itemsData[idx].warnings = {};
            }

            if (nbUsedSlot > 0) {
                if (itemsCloned[idx].rules.maxSlot.message) {
                    rules[itemsCloned[idx].rules.maxSlot.type] = {...itemsCloned[idx].rules.maxSlot};
                }
            }
            if (nbUsedSlot > itemsCloned[idx].nbrSlotMax) {
                itemsData[idx].warnings.maxSlotWarning = {...itemsCloned[idx].rules.maxSlotWarning};
            }

            // check if HD68-IDC has at least 1 IDC-BNC adapter
            if (itemsCloned[idx].type === 'hd68') {
                let shouldWarning = false;

                if (idx < itemsCloned.length - 1) {
                    if (itemsCloned[idx + 1].type !== 'idc-bnc') {
                        shouldWarning = true;
                    }
                } else if (idx === itemsCloned.length - 1) {
                    shouldWarning = true;
                }

                if (shouldWarning) {
                    if (idx in itemsData) {
                        itemsData[idx].warnings.minAdapter = {...itemsCloned[idx].rules.minAdapter};
                    } else {
                        itemsData[idx] = {...itemsCloned[idx]};
                        itemsData[idx].warnings = {};
                        itemsData[idx].warnings.minAdapter = {...itemsCloned[idx].rules.minAdapter};
                    }
                }
            }
        }

        // update state with rules
        this.setState({
            ...this.state,
            columns: {
                ...this.state.columns,
                cart: {
                    ...this.state.columns.cart,
                    itemsData: itemsData,
                }
            },
            rules: {
                ...rules,
            },
        });
    }

    render() {

        const {
            currency,
            currentItemHovered,
            currentMode,
            crateModeSlots,
            crateModeItems,
            items,
            columns,
            rules,
            mobileSideMenuShouldOpen,
            newCardJustAdded,
            isProcessing,
            shouldShowRFQFeedback,
            RFQBodyType,
            RFQBodyOrder,
            isProcessingComplete,
        } = this.state;

        const isMobile = window.deviceIsMobile();
        const isTouch = window.isTouchEnabled();

        return (
            <DragDropContext onDragEnd={this.handleOnDragEnd}>

                <Layout
                    showRFQFeedback={shouldShowRFQFeedback}
                    RFQBodyType={RFQBodyType}
                    RFQBodyOrder={RFQBodyOrder}
                    className="shop"
                    mobileSideMenuShouldOpen={mobileSideMenuShouldOpen}
                    isMobile={isMobile}
                    newCardJustAdded={newCardJustAdded}
                    onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
                    onClickCloseRFQFeedback={this.handleClickCloseRFQFeedback}
                    onClickLoadCustomConf={this.handleLoadCustomConf}
                    items={items}
                    aside={
                        <Backlog
                            currency={currency}
                            items={items}
                            data={columns['backlog']}
                            onClickAddItem={this.handleClickAddItem}
                            onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
                            isMobile={isMobile}>
                        </Backlog>
                    }
                    main={(
                        <OrderPanel
                            onClickToggleMobileSideMenu={this.handleClickToggleMobileSideMenu}
                            onClickOpenImport={this.handleClickOpenImport}
                            isMobile={isMobile}
                            title="Order hardware"
                            description={(<p className="description">Drag and drop the cards you want into the crate below to see how the combination would look like. Setup card's configuration by tapping at the top of the card, most of the options can be modified after shipment. If you have any issues with this ordering system, or if you need other configurations, email us directly anytime at <a href="mailto:sales@m-labs.hk">sales@m-labs.hk</a>. The price is estimated and must be confirmed by a quote.</p>)}
                            crateMode={
                                <CrateMode
                                    items={crateModeItems}
                                    mode={currentMode}
                                    onClickMode={this.handleCrateModeChange}>
                                </CrateMode>}
                            crate={
                                <Crate
                                    cart={
                                        <Cart
                                            nbrSlots={crateModeSlots[currentMode]}
                                            data={columns['cart']}
                                            isMobile={isMobile}
                                            isTouch={isTouch}
                                            itemHovered={currentItemHovered}
                                            onToggleOverlayRemove={this.handleToggleOverlayRemove}
                                            onClickRemoveItem={this.handleDeleteItem}
                                            onClickItem={this.handleShowOverlayRemove}
                                            onCardUpdate={this.handleCardsUpdated}>
                                        </Cart>
                                    }
                                    rules={Object.values(rules).filter(rule => rule)}>
                                </Crate>
                            }
                            summaryPrice={
                                <OrderSummary
                                    currency={currency}
                                    currentMode={currentMode}
                                    modes={crateModeItems}
                                    summary={columns['cart'].items}
                                    itemsData={columns.cart.itemsData}
                                    onMouseEnterItem={this.handleMouseEnterItem}
                                    onMouseLeaveItem={this.handleMouseLeaveItem}
                                    onDeleteItem={this.handleDeleteItem}
                                    onDeleteAllItems={this.handleDeleteAllItems}
                                    onClickSelectItem={this.handleClickSelectItem}>
                                </OrderSummary>
                            }
                            form={
                                <OrderForm
                                    isProcessingComplete={isProcessingComplete}
                                    processingComplete={this.handleProcessingComplete}
                                    isProcessing={isProcessing}
                                    onClickSubmit={this.handleClickSubmit}
                                    onClickShow={this.handleClickShowOrder}>
                                </OrderForm>
                            }>
                        </OrderPanel>
                    )}>
                </Layout>

            </DragDropContext>
        );
    }
}