/**
 * @file Toaster component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';

import Portal from '../Portal';
import Toast from '../_Toast';

import Util from '../_vendors/Util';
import MsgType from '../_statics/MsgType';
import Position from '../_statics/Position';

class Toaster extends Component {

    static Type = MsgType;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.nextKey = 0;
        this.unrenderTimeout = null;

        this.state = {
            visible: false,
            toasts: []
        };

        this.isPositiveSequence = ::this.isPositiveSequence;
        this.clearUnrenderTimeout = ::this.clearUnrenderTimeout;
        this.addToast = ::this.addToast;
        this.removeToast = ::this.removeToast;

    }

    isPositiveSequence(position = this.props.position) {
        return position !== Position.BOTTOM_LEFT && position !== Position.BOTTOM && position !== Position.BOTTOM_RIGHT;
    }

    clearUnrenderTimeout() {
        if (this.unrenderTimeout) {
            clearTimeout(this.unrenderTimeout);
            this.unrenderTimeout = null;
        }
    }

    addToast(toast) {

        this.clearUnrenderTimeout();

        let toasts = this.state.toasts;

        if (this.isPositiveSequence()) {
            toasts.push({...toast, toastsId: this.nextKey++});
        } else {
            toasts.unshift({...toast, toastsId: this.nextKey++});
        }

        this.setState({
            toasts,
            visible: true
        });

    }

    removeToast(toastsId) {

        let toasts = this.state.toasts;

        toasts.splice(toasts.findIndex(item => item.toastsId === toastsId), 1);

        this.setState({
            toasts
        }, () => {
            if (toasts.length < 1) {

                this.clearUnrenderTimeout();

                this.unrenderTimeout = setTimeout(() => {
                    this.setState({
                        visible: false
                    });
                }, 1250);

            }
        });

    }

    componentWillReceiveProps(nextProps) {

        if (nextProps.toasts && nextProps.toasts.length > 0) {

            this.clearUnrenderTimeout();

            let toasts = _.cloneDeep(nextProps.toasts);
            for (let i = 0, len = toasts.length; i < len; i++) {
                if (typeof toasts[i] !== 'object') {
                    toasts[i] = {
                        message: toasts[i]
                    };
                }
                toasts[i].toastsId = this.nextKey++;
            }

            if (this.isPositiveSequence()) {
                toasts = [...this.state.toasts, ...toasts];
            } else {
                toasts = [...toasts.reverse(), ...this.state.toasts];
            }

            this.setState({
                toasts,
                visible: true
            }, () => {
                this.props.onToastPop();
            });

        }

    }

    componentWillUnmount() {
        this.clearUnrenderTimeout();
    }

    render() {

        const {position} = this.props,
            {toasts, visible} = this.state;

        return visible ?
            <Portal className={'toaster' + (position ? ` toaster-position-${position}` : '')}>
                {
                    toasts.length > 0 ?
                        toasts.map(options =>
                            <Toast {...options}
                                   key={options.toastsId}
                                   onRequestClose={this.removeToast}/>
                        )
                        : null
                }
            </Portal>
            :
            null;

    }

};

Toaster.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Children passed into the toaster.
     */
    toasts: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of toast.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the toast.
         */
        style: PropTypes.object,

        /**
         * The type of toast.
         */
        type: PropTypes.oneOf(Util.enumerateValue(MsgType)),

        /**
         * The message of toast.
         */
        message: PropTypes.string,

        /**
         * The icon class name of toast.
         */
        iconCls: PropTypes.string,

        /**
         * The duration of toast.
         */
        duration: PropTypes.number

    }), PropTypes.string, PropTypes.number])),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * Callback function fired when the toaster pop.
     */
    onToastPop: PropTypes.func

};

Toaster.defaultProps = {

    className: '',
    style: null,

    position: Position.BOTTOM_RIGHT

};

export default Toaster;
@@ -180,16 +180,53 @@
 lodash';
+%0Aimport classNames from 'classnames';
 %0A%0Aimport
@@ -3217,16 +3217,34 @@
  const %7B
+className, style, 
 position
@@ -3301,17 +3301,17 @@
 is.state
-;
+,
 %0A%0A      
@@ -3316,44 +3316,30 @@
     
-return visible ?%0A            %3CPortal
+    toasterClassName =
  cla
@@ -3344,18 +3344,18 @@
 lassName
-=%7B
+s(
 'toaster
@@ -3359,25 +3359,30 @@
 ter'
- + (position ? %60 
+, %7B%0A                %5B%60
 toas
@@ -3410,16 +3410,20 @@
 on%7D%60
- : '')%7D%3E
+%5D: position,
 %0A   
@@ -3435,17 +3435,38 @@
         
-%7B
+%5BclassName%5D: className
 %0A       
@@ -3466,32 +3466,37 @@
             
+%7D);%0A%0A
         
 toasts.lengt
@@ -3487,32 +3487,127 @@
     
-toasts.length %3E 0 ?%0A    
+return visible ?%0A            %3CPortal className=%7BtoasterClassName%7D%0A                    style=%7Bstyle%7D%3E%0A                %7B%0A
     
@@ -3613,32 +3613,42 @@
                 
+ toasts &&
  toasts.map(opti
@@ -3654,20 +3654,16 @@
 ions =%3E%0A
-    
         
@@ -3729,20 +3729,16 @@
         
-    
 key=%7Bopt
@@ -3783,20 +3783,16 @@
         
-    
 onReques
@@ -3843,44 +3843,9 @@
     
-    )%0A                        : null
+)
 %0A   
@@ -5136,10 +5136,12 @@
 me: 
-''
+null
 ,%0A  
@@ -5156,16 +5156,34 @@
  null,%0A%0A
+    toasts: null,%0A
     posi

update Toaster