import React, { Component } from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import {transToArray} from '../../utils/Tool'

import Item from './FilterItem'
import ButtonGroup from '../../button-group'
import Button from '../../button'

/**
 * 多选面板<br/>
 * - 可通过selected设置选中的项目,格式如`{key:'ljz',value:'陆家嘴'}`。
 * - 可通过default设置没有选项时的默认显示文字。
 * - 可通过readOnly设置当前面板是否为只读模式。
 * - 可通过buttons设置底部按钮组的样式、文字、回调等,格式如`[{text:'取消', phStyle:'info', onHandle:this.cancelChoose.bind(this), close:true, otherProps: {hollow:true}}]`。
 * - 可通过clickCallBack设置点击显隐panel的回调。
 * - 可通过checkAll设置是否显示全选,默认显示。
 * - 可通过type来判断当前的模式是否简单。
 * 
 * 主要属性和接口:
 * - selected: 默认打开的面板。
 * - default: 是否显示筛选头部。
 * - readOnly: 是否只读。
 * - buttons: 按钮组。
 * - clickCallBack: 点击panel显隐的回调。
 * - checkAll: 是否显示全选。
 * - type: 简单模式。
 * 
 * 如:
 * ```code
 *  const buttons = [
 *      {onHandle: this.onSubmit.bind(this)}
 *  ]
 * ...
 *  <FilterContainer>
 *      <PanelCheckbox readOnly selected={{key:'s_flower,f_bbc',value:'花店,本帮江浙菜'}} buttons={buttons} checkAll={false} clickCallBack={(show)=>{console.log(show)}}>
 *          <ItemGroup mainKey='ms' label={<span style={{color:'red'}}>美食</span>}>
 *              <Item itemKey='f_bbc'>本帮江浙菜</Item>
 *              ...
 *          </ItemGroup>
 *          <ItemGroup mainKey='dy' label='电影'>
 *              <Item itemKey='m_p'>私人影院</Item>
 *              ...
 *          </ItemGroup>
 *          ...
 *      </PanelCheckbox>
 *  </FilterContainer>
 * 或
 * <FilterContainer>
 *      <PanelCheckbox readOnly selected={{key:'s_flower,f_bbc',value:'花店,本帮江浙菜'}} buttons={buttons} type='simple'>
 *          <Item itemKey='f_bbc'>本帮江浙菜</Item>
 *          ...
 *      </PanelCheckbox>
 *  </FilterContainer>
 * ```
 *
 * @class FilterPanelCheckbox
 * @module 筛选控件
 * @extends Component
 * @constructor
 * @since 2.2.0
 * @demo ph-filter|ph-filter.js {展示}
 * @show true
 * */
export default class FilterPanelCheckbox extends Component{
    constructor(props,context){
        super(props,context);

        this.choose = this.dealWithSelected(props)
        this.nameList = {}

        this.state={
            activeGroupIndex: props.index,
            allChecked: {},
            itemChecked: {},
            itemDisabled: {},
            selected: this.dealWithSelected(props),
            selectedName: this.dealWithSelected(props, 'value')
        };
    }

    static propTypes= {
        /**
         * panel下选中的item的key、value组成的对象,用于设置该panel初始状态下选中的item项
         * @property selected
         * @type Object 如{key:'ljz,xjh',value:'陆家嘴,徐家汇'}
         * */
        selected: PropTypes.shape({
            key: PropTypes.oneOfType(PropTypes.number, PropTypes.string),
            value: PropTypes.oneOfType([PropTypes.string,PropTypes.element])
        }),
        /**
         * 当不设置panel的选中项时(不选择任何item),可以设置一个默认字符展示在filter上
         * @property default
         * @type String
         * */
        default: PropTypes.string,
        /**
         * panel是否为只读模式
         * @property readOnly
         * @type Boolean
         * */
        readOnly: PropTypes.bool,
         /**
         * 按钮数组
         * @property buttons
         * @type Array
         * */
        buttons: PropTypes.array,
         /**
         * 是否可以全选
         * @property checkAll
         * @type Boolean
         * @default true
         * */
        checkAll: PropTypes.bool
    }

    static defaultProps = {
        selected: {},
        checkAll: true
    }

    componentWillReceiveProps(nextProps){
        if(this.state.selected !== this.dealWithSelected(nextProps)){
            this.setState({
                selected: this.dealWithSelected(nextProps),
                selectedName: this.dealWithSelected(nextProps, 'value')
            })
        }
    }

    dealWithSelected(props, param){
        let key = param || 'key'
        if(props.selected && props.selected[key]) return transToArray(props.selected[key])
        else return []
    }

    deleteFromArray(val){
        let {selected, selectedName} = this.state,
            _index = selected.indexOf(val)

        if(_index>-1){
            selected.splice(_index, 1)
            selectedName.splice(_index, 1)
        }
    }
 
    mainKeyChange(key){
        this.setState({
            activeGroupIndex: key
        });
    }

    onAllItemChange(mainKey, itemKey, name, e){
        let {selected, selectedName, allChecked, itemChecked} = this.state
        
        allChecked[mainKey] = e.target.checked
        // 全选或全不选
        for(let i in itemChecked[mainKey]){
            itemChecked[mainKey][i] = e.target.checked

            if(e.target.checked){ // 全选
                if(selected.indexOf(i)==-1 && !this.state.itemDisabled[mainKey][i]){
                    selected.push(i.toString())
                    selectedName.push(this.nameList[mainKey][i])
                }
            }else{ // 全不选
                this.deleteFromArray(i)
            }
        }
        
        this.setState({
            allChecked: allChecked,
            itemChecked: itemChecked
        });

        // if(this.props.getChooseData) this.props.getChooseData(choose.join());
    }

    onItemChange(mainKey, itemKey, name, e){
        let {selected, selectedName, allChecked, itemChecked, itemDisabled} = this.state

        itemChecked[mainKey][itemKey] = e.target.checked
        
        if(!e.target.checked){ // 其中一个不选时去掉全选
            allChecked[mainKey] = false;
            this.deleteFromArray(itemKey.toString())
        }

        if(e.target.checked){
            let count = true;
            if(selected.indexOf(itemKey)==-1){
                selected.push(itemKey.toString())
                selectedName.push(name)
            }
            for(let i in itemChecked[mainKey]){
                if(!itemChecked[mainKey][i] && !itemDisabled[mainKey][i]){
                    count = false;
                    break;
                }
            }
            if(count) allChecked[mainKey] = true;
        }
        
        this.setState({
            allChecked: allChecked,
            itemChecked: itemChecked
        });

        // if(this.props.getChooseData) this.props.getChooseData(selected.join());
    }

    renderMainMenuList(){
        let self = this;
        
        return React.Children.map(this.props.children,function(menu,index){
            return (
                React.cloneElement(menu,{
                    active:self.state.activeGroupIndex==index,
                    groupIndex:index,
                    readOnly:self.props.readOnly,
                    mainKeyChange:self.mainKeyChange.bind(self)
                })
            );
        })
    }

    renderSubMenuList(mainMenuList){
        let {selected} = this.state,
            {itemChecked, itemDisabled} = this.state;
        var mainMenu, self=this, {checkAll} = this.props;

        mainMenu = React.Children.map(mainMenuList,function(menu){
            let mainKey = menu.props.mainKey || 0;
            
            if(menu.props.groupIndex==self.state.activeGroupIndex){
                return self.renderSubMenuCore(menu.props.children, selected, mainKey);
            }
        });

        return mainMenu;
    }

    renderExtra(showExtra, selected){
        let newExtra = showExtra,
            numElem = ` <i>${selected.length}</i> `
        
        if(showExtra){
            if(showExtra.indexOf('#')!=-1){
                newExtra = <span dangerouslySetInnerHTML={{__html: showExtra.replace('#', numElem)}}></span>
            }
        }
        return newExtra
    }

    renderButtons(){
        let {buttons, panelIndex, showExtra} = this.props,
            {selected, selectedName} = this.state,
            self = this
        console.log('>>selected' ,selected)
        return buttons? (
            <ButtonGroup phType='footer' extra={this.renderExtra(showExtra, selected)}>
                {
                    buttons.map((button, index)=>{
                        return (
                            <Button key={index} {...button.otherProps} phSize='lg' phStyle={button.phStyle || 'primary'}
                                onClick={()=>{
                                    if(button.onHandle){
                                        button.onHandle(selected.join(), selectedName.join())
                                        if(button.close) self.props.categoryChange(panelIndex, {key:selected.join(), value: selectedName.join()})
                                    }
                                }
                            }>
                                {button.text || '确定'}
                            </Button>
                        )
                    })
                }
            </ButtonGroup>
        ): null
    }

    renderMenuList(){
        let {selected} = this.state,
            menuList = this.renderSubMenuCore(this.props.children, selected, 0)
        return menuList
    }

    renderSubMenuCore(children, selected, mainKey){
        let {itemChecked, itemDisabled, allChecked} = this.state,
            {checkAll} = this.props
        let subMenu = [], checkedCount = 0, disabledCount = 0, sum = 0, self = this

        React.Children.map(children,function(item){
            let key = item.props.itemKey, disabled = item.props.disabled
            
            itemChecked[mainKey] = itemChecked[mainKey] || {}
            itemDisabled[mainKey] = itemDisabled[mainKey] || {}
            self.nameList[mainKey] = self.nameList[mainKey] || {}

            if(itemChecked[mainKey][key]==undefined || self.choose != selected){ // 兼容通过请求获取choose的情况
                itemChecked[mainKey][key] = selected.indexOf(key.toString())!=-1
            } 
            if(itemDisabled[mainKey][key]==undefined || self.choose != selected){
                itemDisabled[mainKey][key] = disabled
            }
            if(self.nameList[mainKey][key]==undefined || self.choose != selected){
                self.nameList[mainKey][key] = item.props.children
            }
            
            if(itemChecked[mainKey][key]) checkedCount++
            if(disabled){
                self.deleteFromArray(key.toString())
                disabledCount++
            } 
            sum ++
            
            subMenu.push(React.cloneElement(item,{
                active:false,
                readOnly:self.props.readOnly,
                categoryChange:self.props.categoryChange,
                panelIndex:self.props.panelIndex,
                // new props
                checked: itemChecked[mainKey][key],
                // selected:self.props.selected,
                filterType: 'checkbox',
                mainKey: mainKey,
                onItemChange:self.onItemChange.bind(self)
            }));
        });
        
        // new一个全部的elemecontext
        if(allChecked[mainKey]==undefined || self.choose != selected){
            if(checkedCount+disabledCount==sum) allChecked[mainKey] = true
            else allChecked[mainKey] = false
        }
        
        if(checkAll) subMenu.unshift(<Item active={false} key={mainKey} itemKey={mainKey} mainKey={mainKey} disabled={disabledCount==sum}
            filterType='checkbox' checked={allChecked[mainKey]} 
            onItemChange={self.onAllItemChange.bind(self)}>全部</Item>)

        return subMenu
    }

    isSimple(){
        let {type} = this.props
        return type=='simple'
    }

    renderSimpleMenu(className){
        let menuList = this.renderMenuList()

        return (
            <div className={classnames('ph-row ph-tabs ph-tabs-vertical', className)} >
                <div className='ph-col ph-tab-bd'>{menuList}</div>
            </div>
        )
    }

    renderMenu(className){
        let mainMenuList = this.renderMainMenuList(),
            subMenuList = this.renderSubMenuList(mainMenuList)

        return (
            <div className={classnames('ph-row ph-tabs ph-tabs-vertical', className)} >
                <div className='ph-col ph-col-33 ph-tab-navs'>{mainMenuList}</div>
                <div className='ph-col ph-tab-bd'>{subMenuList}</div>
            </div>
        )
    }

    render(){
        let {className, buttons, show, type, children} = this.props
        
        return show? (
            <div className={classnames('ph-filter-selector', buttons? 'ph-filter-selector-buttons':'')}>
                {this.isSimple()? this.renderSimpleMenu(className) : this.renderMenu(className)}
                {this.renderButtons()}
            </div>
        ): null
    }
}