var hasOwn = {}.hasOwnProperty;

function classNames () {
    var classes = [];

    for (var i = 0; i < arguments.length; i++) {
        var arg = arguments[i];
        if (!arg) {
            continue;
        }

        var argType = typeof arg;

        if (argType === "string" || argType === "number") {
            classes.push(arg);
        } else if (Array.isArray(arg) && arg.length) {
            var inner = classNames.apply(null, arg);
            if (inner) {
                classes.push(inner);
            }
        } else if (argType === "object") {
            for (var key in arg) {
                if (hasOwn.call(arg, key) && arg[key]) {
                    classes.push(key);
                }
            }
        }
    }

    return classes.join(" ");
}

var defaultProps = {
    show: false,
    extraClass: "",
    contentExtraClass: "",
    align: "center",
    onMaskTap: function onMaskTap() {},
    contentOffset: [0, 0],
    maskOffset: [0, 0],
    maskExtraClass: "",
    animation: "",
    onShow: function onShow() {},
    onHide: function onHide() {},
    width: null,
    height: null,
    delayBeforeAnimationStart: 100
};

// 默认提供的动画效果
var ANIMATION_MAP = {
    fade: { animation: ["fade-in", "fade-out"], duration: 200 },
    zoom: { animation: ["zoom-in", "zoom-out"], duration: 300 },
    "fade-in-up": { animation: ["fade-in-up", "fade-out-down"], duration: 200 },
    "fade-in-down": { animation: ["fade-in-down", "fade-out-up"], duration: 200 }
};

var Component = React.Component;
function RealModal(props, context) {
    Component.call(this, props, context);
    this.state = {
        show: props.show,
        animation: this.getAnimationClass(props.animation, props.show)
    };
}

function inherit(SubClass, SupClass, cb) {

    function Bridge() {}
    Bridge.prototype = SupClass.prototype;

    let fn = (SubClass.prototype = new Bridge());

    // 避免原型链拉长导致方法查找的性能开销
    Object.assign(fn, SupClass.prototype);
    fn.constructor = SubClass;
    if(cb){
        cb(fn);
    }
    return fn;
}
inherit(RealModal, Component, function(fn){
    fn.componentDidMount = function () {
        if (this.props.show) {
            this.props.onShow();
        }
    };
    
    fn.componentWillReceiveProps = function (nextProps) {
        this.toggleShowStatus(nextProps);
    };
    fn.componentWillUnmount = function () {
        clearTimeout(this.hideTimeout);
        clearTimeout(this.showTimeout);
    };
    fn.getAnimationClass = function(name, isShow) {
        var contentAnimation = "",
            duration = 0;
        if (name) {
            var ani = this.props.animation;
            var targetMap = ani && typeof ani === "object" ? ani : ANIMATION_MAP[name];
            if (targetMap) {
                contentAnimation = [targetMap.animation[isShow ? 0 : 1], "ani"].join(" ");
                duration = targetMap.duration;
            }
        }
        return { name: contentAnimation, duration: duration };
    };
    fn.toggleShowStatus = function (nextProps) {
        var _this2 = this;
    
        var current = this.state.show;
        var next = nextProps.show;
        var _props = this.props,
            onShow = _props.onShow,
            onHide = _props.onHide;
        // 如果新属性的show是true并且模态框处于打开状态
    
        if (!next && current) {
            // 提取需要指定的动画
            var animationData = this.getAnimationClass(nextProps.animation, next);
            clearTimeout(this.showTimeout);
            // show动画开始前执行onHide回调
            onHide();
            // 先走关闭动画
            this.setState({ animation: animationData });
            // 等到动画结束后处理整个modal的show状态,并且保存timeout引用
            this.hideTimeout = setTimeout(function () {
                _this2.setState({ show: false });
            }, animationData.duration);
        } else if (next && !current) {
            // 清理关闭timeout
            // 写这一行的目的是用户可能在关闭的同时打开modal
            clearTimeout(this.hideTimeout);
            this.setState({ show: next });
            this.contentDom.style.visibility = "hidden";
    
            // 如果直接运行动画会出现闪烁,这里先将contentDom隐藏然后再运行动画
            this.showTimeout = setTimeout(function () {
                // hide动画开始前执行onShow回调
                onShow();
                _this2.setState({ animation: _this2.getAnimationClass(nextProps.animation, next) });
                _this2.contentDom.style.visibility = "visible";
            }, this.props.delayBeforeAnimationStart);
        }
    };
    fn.render = function() {
        var _this3 = this;
    
        var _state = this.state,
            show = _state.show,
            animation = _state.animation;
        var duration = animation.duration,
            name = animation.name;
        var _props2 = this.props,
            extraClass = _props2.extraClass,
            onMaskTap = _props2.onMaskTap,
            maskOffset = _props2.maskOffset,
            contentOffset = _props2.contentOffset,
            align = _props2.align,
            contentExtraClass = _props2.contentExtraClass,
            width = _props2.width,
            height = _props2.height;
    
        var containerClass = classNames("yo-modal", extraClass, "yo-modal-" + align);
        var contentClass = classNames("cont", contentExtraClass, name);
        console.log("modal render....");
        return React.createElement(
            "div",
            {
                ref: "container",
                className: containerClass,
                onClick: function onTouchTap(evt) {
                    if (evt.target === _this3.refs.container) {
                        onMaskTap(evt);
                    }else{
                        console.log("没点中");
                    }
                },
                style: Object.assign({
                    top: parseInt(maskOffset[0], 10),
                    bottom: parseInt(maskOffset[1], 10),
                    transform: "translate3d(0,0,0)",
                    WebkitTransform: "translate3d(0,0,0)"
                }, show ? null : { display: "none" })
            },
            React.createElement(
                "div",
                {
                    className: contentClass,
                    ref: function ref(component) {
                        console.log("=======ref",component);
                        _this3.contentDom = component;
                    },
                    style: {
                        position: "relative",
                        top: parseInt(contentOffset[1], 10) || 0,
                        left: parseInt(contentOffset[0], 10) || 0,
                        WebkitAnimationDuration: duration + "ms",
                        animationDuration: duration + "ms",
                        width: width,
                        height: height
                    }
                },
                this.props.children
            )
        );
    };
});


RealModal.defaultProps = defaultProps;

function Modal(props, context) {
    Component.call(this, props, context);
}

inherit(Modal, Component, function(fn){
    fn.componentDidMount = function () {
        this.wrapper = document.createElement("div");
        document.body.appendChild(this.wrapper);
        this.appendWrapperToDocBody();
    };
    fn.componentDidUpdate = function () {
        this.appendWrapperToDocBody();
    };
    fn.componentWillUnmount = function componentWillUnmount() {
        document.body.removeChild(this.wrapper);
    };

    fn.appendWrapperToDocBody = function appendWrapperToDocBody() {
        var realmodal = React.createElement(
            RealModal,
            this.props,
            this.props.children
        );
        ReactDOM.unstable_renderSubtreeIntoContainer(this, realmodal, this.wrapper);
    };
    fn.render = function () {
        return null;
    };
});    

