import React from 'react'
import PropTypes from 'prop-types'
import Component from '../utils/Component'
import classnames from 'classnames'
import {closest} from '../utils/Tool'
import Logger from '../utils/logger'

import MenuHeader from './MenuHeader'
import MenuBody from './MenuBody'
import MenuList from './MenuList'
import MenuItem from './MenuItem'

import '../style'
import 'phoenix-styles/less/modules/menu.less'

/**
 * <h5>菜单组件,主要包括组件:</h5>
 * <strong><a href='../classes/Menu.html'>Menu 菜单</a></strong><br/>
 * <strong><a href='../classes/MenuHeader.html'>MenuHeader 菜单头部</a></strong><br>
 * <strong><a href='../classes/MenuBody.html'>MenuBody 菜单主体</a></strong><br>
 * <strong><a href='../classes/MenuList.html'>MenuList 菜单导航列表</a></strong><br>
 * <strong><a href='../classes/MenuItem.html'>MenuItem 菜单导航列表项</a></strong><br>
 * <h6>点击以上链接或者左侧导航栏的组件名称链接进行查看</h6>
 * @module 菜单组件
 * @main 菜单组件
 * @static
 */
/**
 * 菜单组件<br/>
 - 可通过visible设置菜单初始是否可见,默认不可见。
 - 不设置ceiling时默认菜单不吸顶,设置ceiling为具体数值时表示从当前距离开始吸顶,设置0表示至始至终吸顶。
 - 可通过clickCallback函数设置菜单打开收起的回调函数。
 *
 * 主要属性和接口:
 * - visible:初始展开或收起的状态, 默认false收起。
 * - ceiling:设置吸顶的距离, 默认不吸顶, 设置0表示始终吸顶。
 * - clickCallback:菜单打开关闭时的回调函数。 <br/>
 * 如:
 * ```code
 *     <Menu ceiling={100} visible={true} clickCallback={(visible)=>{console.log(visible);}}>
 *         <Menu.Header>
 *             标题一
 *         </Menu.Header>
 *         <Menu.Body>
 *             ...
 *         </Menu.Body>
 *     </Menu>
 * ```
 *
 * @class Menu
 * @module 菜单组件
 * @extends Component
 * @constructor
 * @since 1.3.0
 * @demo menu|menu.js {展示}
 * @show true
 * */

class Menu extends Component{

    static propTypes = {
        /**
         * 样式前缀
         * @property classPrefix
         * @type String
         * @default 'menu'
         * */
        classPrefix: PropTypes.string,
        /**
         * 标签tagName
         * @property componentTag
         * @type String
         * */
        componentTag:PropTypes.string,
        /**
         * 是否可见标识
         * @property visible
         * @type Boolean
         * @default false
         * */
        visible: PropTypes.bool,
        /**
         * 点击收起展开的回调函数
         * @method clickCallback
         * @param {boolean} visible 当前收起展开的状态
         * @type Function
         * */
        clickCallback: PropTypes.func,
        /**
         * 是否滚动吸顶, 默认不吸顶(false); 设置确定的数字从当前距离开始吸顶 
         * @property ceiling
         * @type Number
         * @default 不设置
         * */
        ceiling: PropTypes.number
    };

    static defaultProps = {
        visible: false,
        classPrefix:'menu',
        componentTag:'div',
        classMapping : {}
    };

    constructor(props, context) {
        super(props, context)

        new Logger('Menu')

        this.handleWindowScroll = this.handleWindowScroll.bind(this)

        this.state = {
            ceiling: !(props.ceiling === undefined || props.ceiling > 0),
            headerHeight: 0
        }

        // 是否滚动吸顶
        if(props.ceiling === undefined || props.ceiling === 0) return
        
        window.addEventListener('scroll', this.handleWindowScroll, false)
    }
    
    handleWindowScroll(){
        if(document.body.scrollTop >= this.props.ceiling){
            if(!this.state.ceiling) this.setState({ceiling: true});
        }else{
            if(this.state.ceiling) this.setState({ceiling: false});
        }
    }

    componentDidMount(){
        setTimeout(()=>{
            this.menuPlaceholder.style.height = this.menuCeiling.offsetHeight +'px';
            this.setState({headerHeight: this.menuCeiling.offsetHeight})
        },0);
    }

    renderChildren(){
        let _this = this,
            newChildren = [],
            {visible, clickCallback} = this.props

        React.Children.forEach(this.props.children, function(child, index){
            newChildren.push(React.cloneElement(child, {
                key: index,
                visible: visible,
                clickCallback: clickCallback,
                headerHeight: _this.state.headerHeight
            }));
        });

        return newChildren;
    }

    componentWillUnmount(){
        window.removeEventListener('scroll', this.handleWindowScroll, false);
    }

    renderMenu(){
        let {componentTag:Component, className} = this.props;

        return (
            <Component {...this.otherProps} className={classnames(
                this.getProperty(true),
                this.setPhPrefix('placeholder'),
                className
            )} ref={(menuPlaceholder)=>{this.menuPlaceholder=menuPlaceholder}}>
                <div className={this.state.ceiling? this.setPhPrefix('ceiling'):''} ref={(menuCeiling)=>{this.menuCeiling=menuCeiling}}>
                    {this.renderChildren()}
                </div>
            </Component>
        )
    }

    render(){
        return this.renderMenu()
    }
}

Menu.Header = MenuHeader
Menu.Body = MenuBody
Menu.List = MenuList
Menu.Item = MenuItem

export default Menu