/* eslint-disable no-console */
import React, { PropTypes } from 'react';
import { autobind } from 'core-decorators';
import { ExtendButton } from '../../../components';
import { Table, Button, Row, Col, Tooltip, Modal } from '../../../components/mxa';
import { ContentRender } from '../../system/longRunOpt';
import { LIST_SELECTTYPE, BUTTON_POSITION, BUTTON_RELATEDDATA } from '../../constant/dictCodes';
import { arr2obj, handleFilterItems, handleOrderItems, renderColumn } from './util';
import { getMenuItemByKeyPaths, getMenuItemByFunc, getMenuItemAndPathByFunc, searchBeforeAndAfter } from '../../utils/MenuHelper';
import SideMenu from '../info/sideMenu';
import processMenu from './processMenu';
import { PAGE_TYPE_SUMMARY_LIST } from '../../constant/dictActions';
import ToolBar from './toolBar';
import { isEmpty } from '../../utils/EmptyUtils';
import { trimStart } from '../../utils/StringUtils';
import EditableCell from './editableCell';
import { createFunc } from '../../utils/JSExecutor';
import { isApply, isReview } from '../../utils/ProcessHelper';

class ListView extends React.Component {
  static propTypes = {
    prefixCls: PropTypes.string,
    isModal: PropTypes.bool,
    isInfo: PropTypes.bool,
    modalCallback: PropTypes.func,
    inject: PropTypes.object, // inject for customize, key is 'buttonDescription'
    // hiddenSearchBar: PropTypes.bool,
  };

  static defaultProps = {
    prefixCls: 'mx-list',
    isModal: false,
    isInfo: false,
  };

  constructor(props) {
    super(props);
    // initial state
    this.isApply = isApply(this.props.domainLink);
    this.isReview = isReview(this.props.domainLink);
    // this.contentList = this.props.dataSource.pageResult.contentList || [];
    this.state = this._processData(this.props.dataSource);
  }

  @autobind
  _renderColumnAction(text, record, buttons, mainEntityKey) {
    const { prefixCls, query, inject } = this.props;
    const toolbarClassName = `${prefixCls}-inline-toolbar`;
    const buttonClassName = `${prefixCls}-inline-button`;
    return (
      <div key="inline-operation" className={toolbarClassName}>
        {
          buttons.map((item, index) => (
            <ExtendButton
              {...item}
              inline={true}
              key={index}
              mainEntityKey={mainEntityKey}
              record={record}
              inject={inject}
              className={buttonClassName}
              query={query}
              onRefresh={this._onSearch}
            />
          ))
        }
      </div>
    );
  }

  @autobind
  onCellChange(record, name) {
    return value => {
      // console.log('mainEntityKey:', this.state.mainEntityKey);
      console.log('record', record);
      console.log('name: ', name, ' value: ', value);
      // TODO: save api
      // this.props.exec(() => this.props.fetch('/rowSave', { ...record, [name]: value }).then(response => {
      //   console.log('result: ', response);
      // })).then(() => {
      //   const dataSource = this.state.dataSource.map(item => {
      //     if (item[this.state.mainEntityKey] === record[this.state.mainEntityKey]) {
      //       return { ...item, [name]: value };
      //     }
      //     return item;
      //   });
      //   // 修改本地
      //   this.setState({ dataSource: dataSource });
      // });
      return true;
    };
  }

  @autobind
  _renderColumn(text, fieldContent) {
    const temp = renderColumn(text, fieldContent);
    if (typeof temp === 'string' && temp.length > 20) {
      return (
        <Tooltip title={temp} placement="top">
          <span>{temp.substring(0, 18) + '...'}</span>
        </Tooltip>
      );
    }
    return (
      <span>{temp}</span>
    );
  }

  @autobind
  _processData(data) {
    const buttons = { row: [], top: [] };
    if (data.buttons) {
      buttons.row = data.buttons.filter(item => item.displayPosition === BUTTON_POSITION.ROW);
      buttons.top = data.buttons.filter(item => item.displayPosition === BUTTON_POSITION.TOP);
    }

    // const orderItems = handleOrderItems(data.orderItems);
    const ordered = data.orderItems && data.orderItems.length > 0;
    let mainEntityKey = '';
    const columns = [];
    data.fields && data.fields.sort((a, b) => a.index - b.index).forEach((item, index) => {
      if (item.isMainEntityKey) mainEntityKey = item.name;
      if (this.dealIsVisibleField(item.isVisible)) {
        columns.push({
          width: (item.displayColumnLength || 18) * 12,
          key: index,
          title: item.description,
          dataIndex: item.name,
          // sorter: !!orderItems[item.name],
          render: (text, record) => {
            const fieldContent = this.state.fieldsObject[item.name];
            if (item.editable) {
              return (
                <EditableCell
                  value={text}
                  renderColumn={this._renderColumn}
                  getCurrentRecord={() => this.state.dataSource.find(element => element[this.state.mainEntityKey] === record[this.state.mainEntityKey])}
                  onChange={this.onCellChange(record, item.name)}
                  fieldContent={fieldContent}
                />
              );
            }
            return this._renderColumn(text, fieldContent);
          }
        });
      }
    });

    // fix first column
    // if (columns.length > 0) {
    //   columns[0].fixed = true;
    // }

    // add operation
    if (buttons && buttons.row && buttons.row.length > 0) {
      columns.push({
        key: 'inline-operation',
        title: '操作',
        dataIndex: 'inline-operation',
        // fixed: 'right',
        // width: 300,
        render: (text, record) => this._renderColumnAction(text, record, buttons.row, mainEntityKey),
      });
    }

    const variantFields = Object.assign({}, this.props.query, this.props.params);
    if ((this.isApply || this.isReview) && !variantFields.menu) {
      if (this.isApply) {
        variantFields.menu = 'BPMApply.QueryToDo';
      }
      if (this.isReview) {
        variantFields.menu = 'BPMReview.QueryToDo';
      }
    }

    const pageIndex = data && data.pageResult && data.pageResult.pageIndex;
    const itemsPerPage = data && data.pageResult && data.pageResult.itemsPerPage;
    const pagination = {
      total: data && data.pageResult && data.pageResult.totalItems,
      pageSize: itemsPerPage,
      showSizeChanger: false,
      showQuickJumper: true,
      showTotal: total => `共 ${total} 项`,
    };

    const fieldsObject = arr2obj(data.fields, 'name');
    const filters = handleFilterItems(data.filterItems, fieldsObject);
    const dataSource = (data.pageResult.contentList && data.pageResult.contentList.map((r, key) => {
      return { key: key + '-' + pageIndex + '-' + r[mainEntityKey], ...r };
    })) || [];
    this.contentList = dataSource;
    const selectedType = data.selectType;
    // const selectedType = this.props.isModal ? LIST_SELECTTYPE.RADIO : data.selectType;
    return {
      columns,
      dataSource,
      buttons,
      pagination,
      fieldsObject,
      filters,
      pageIndex,
      itemsPerPage,
      requestFilterFields: [],
      variantFields,
      ordered,
      orderFields: [],
      mainEntityKey,
      selectedType,
      selectedRowKeys: this._initSelectedKeys(dataSource, mainEntityKey),
      selectedRows: [],
      advancedSearch: null,
      isAdvance: false, // 查询模式
      y: null, // 控制表格头部fix
    };
  }

  _initSelectedKeys = (dataSource, mainEntityKey) => {
    if (!this.props.extraData || !mainEntityKey) return [];
    return dataSource.reduce((selectedKeys, item) => {
      if (this.props.extraData.filter(k => k === item[mainEntityKey]).length > 0) {
        selectedKeys.push(item.key);
      }
      return selectedKeys;
    }, []);
  };

  @autobind
  dealIsVisibleField(isVisible) {
    if (isVisible === 'true') {
      return true;
    } else if (isVisible === 'false') {
      return false;
    } else if (isVisible && isVisible !== false && isVisible !== true) {
      return createFunc(isVisible)();
    }
    return isVisible;
  }

  @autobind
  _onFilterChange(value, isAdvance) {
    console.log(`_onFilterChange ${value}`);
    this.state.requestFilterFields = value;
    this.state.isAdvance = !!isAdvance;
    this.state.pageIndex = 1;
    this.setState({
      isLoading: true,
    }, () => {
      this._onSearch(null, true);
    });
  }

  @autobind
  _onChange(pagination, filters, sorter, isKeepSelectedKeys) {
    console.log('params', pagination, filters, sorter);
    if (this.state.ordered && !isEmpty(sorter)) {
      const orderFields = [];
      orderFields.push({
        orderField: sorter.field,
        orderType: sorter.order === 'descend' ? 'DESC' : 'ASC',
      });

      this.setState({
        pageIndex: pagination.current,
        itemsPerPage: pagination.pageSize,
        orderFields,
      }, () => {
        this._onSearch(isKeepSelectedKeys);
      });
    } else {
      this.setState({
        pageIndex: pagination.current,
        itemsPerPage: pagination.pageSize,
        // orderFields,
      }, () => {
        this._onSearch(isKeepSelectedKeys);
      });
    }
  }

  @autobind
  _onSearch(isKeepSelectedKeys, shouldScrollToTop) {
    console.log('***-----LIST REFRESH-----***');
    const searchUrl = trimStart(this.props.domainLink.replace(/^(.*\/)render(\w*)$/, '$1search$2'), '/');
    const param = {
      pageIndex: this.state.pageIndex,
      itemsPerPage: this.state.itemsPerPage,
      requestParamsBean: Object.assign({}, this.state.variantFields, this.state.requestParamsBean), // issue #5
      requestFilterFields: this.state.requestFilterFields,
      requestOrderFields: this.state.orderFields,
      isAdvance: this.state.isAdvance,
    };
    this.props.exec(() => this.props.fetch(searchUrl, param).then(data => {
      if (!data || !data.contentList) return { totalItems: data.totalItems, itemsPerPage: data.itemsPerPage, contentList: [] };
      if (isKeepSelectedKeys) return { totalItems: data.totalItems, itemsPerPage: data.itemsPerPage, contentList: [...this.state.dataSource, ...data.contentList] };
      return data;
    })
      .then(data => {
        const dataSource = (data.contentList.map((r, key) => {
          return { key: key + '-' + this.state.pageIndex + '-' + r[this.state.mainEntityKey], ...r };
        })) || [];
        this.contentList = [...dataSource];
        const pagination = {
          current: this.state.pageIndex,
          total: data && data.totalItems,
          pageSize: data.itemsPerPage,
          showSizeChanger: false,
          showQuickJumper: true,
          showTotal: total => `共 ${total} 项`,
        };
        shouldScrollToTop && (this.shouldScrollToTop = true);
        this.setState({
          dataSource,
          pagination,
          selectedRowKeys: isKeepSelectedKeys === true ? this.state.selectedRowKeys : [],
          selectedRows: isKeepSelectedKeys === true ? this.state.selectedRows : [],
          isLoading: false
        });
      }));
  }

  @autobind
  _getRelatedState(item) {
    if (item.relatedData === BUTTON_RELATEDDATA.SINGLE) {
      if (this.state.selectedRowKeys.length !== 1) {
        return true;
      }
      const relatedItems = (item.relatedItems && item.relatedItems.relatedItemList) || [];
      const prolog = (item.relatedItems && item.relatedItems.prolog);
      if (prolog === 'AND') {
        return relatedItems.some(i => this.state.selectedRows[0][i.relatedKey] !== i.relatedValue);
      }
      if (prolog === 'OR') {
        return relatedItems.every(i => this.state.selectedRows[0][i.relatedKey] !== i.relatedValue);
      }
    }
    if (item.relatedData === BUTTON_RELATEDDATA.MULTIPLE && this.state.selectedRowKeys.length < 1) {
      return true;
    }
    return false;
  }

  _modalSubmit = () => {
    const { selectedType, mainEntityKey } = this.state;
    if (this.props.modalCallback) {
      this.props.modalCallback(
        this.contentList.filter(item => this.state.selectedRowKeys.indexOf(item.key) >= 0),
        selectedType,
        mainEntityKey
      );
    }
  };

  @autobind
  _renderTopButtons(filter) {
    const { prefixCls, query, inject, dataSource } = this.props;
    const { selectedType, mainEntityKey } = this.state;
    if (this.props.isModalInput) {
      return [
        <div className={'common-btn' + (this.state.selectedRowKeys.length <= 0 ? ' disable' : '')}>
          <a
            onClick={this._modalSubmit}
            disabled={this.state.selectedRowKeys.length <= 0}
          >确定</a>
        </div>
      ];
    }

    let btnJsonObject = this.state.buttons && this.state.buttons.top && this.state.buttons.top;
    if (filter) {
      btnJsonObject = btnJsonObject.filter(filter);
    }
    const btns = btnJsonObject.map(item => {
      let ButtonComp = ExtendButton;
      if (this.props.renderButtonsSelf) {
        const myBtn = this.props.renderButtonsSelf(item, this.props);
        if (myBtn) {
          ButtonComp = myBtn;
        }
      }
      return (
        <ButtonComp
          inline={false}
          buttonProps={{
            type: 'ghost',
          }}
          {...item}
          disabled={this._getRelatedState(item)}
          key={item.buttonDescription}
          mainEntityKey={this.state.mainEntityKey}
          selectedType={this.state.selectedType}
          record={this.state.selectedRows}
          query={query}
          inject={inject}
          isModal={this.props.isModal}
          modalCallback={this.props.modalCallback}
          onRefresh={this._onSearch}
        />
      );
    });
    if (this.props.createTopButtons) {
      this.props.createTopButtons(btns);
      return (<div />);
    }
    return btns;
  }


  @autobind
  _onRowClick(record, index) {
    if (this.state.selectedType === LIST_SELECTTYPE.INLINE) return;
    console.log('onRowClick ==> ', record, index);

    const selectedIndex = this.state.selectedRowKeys.indexOf(record.key);
    if (selectedIndex > -1) {
      this.setState({
        selectedRowKeys: this.state.selectedRowKeys.filter(item => item !== record.key),
        selectedRows: this.state.selectedRows.filter(item => item.key !== record.key),
      });
    } else if (this.state.selectedType === LIST_SELECTTYPE.RADIO) {
      this.setState({
        selectedRowKeys: [record.key],
        selectedRows: [record],
      });
    } else {
      this.setState({
        selectedRowKeys: this.state.selectedRowKeys.concat(record.key),
        selectedRows: this.state.selectedRows.concat(record),
      });
    }
  }

  renderList(isProcess) {
    // const selectedRows = [];
    const rowSelection = this.state.selectedType === LIST_SELECTTYPE.INLINE ? null : {
      type: this.state.selectedType,
      onChange: (selectedRowKeys, selectedRows) => {
        console.log('onChange ==> ', `selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
        this.setState({ selectedRowKeys, selectedRows });
      },
      onSelect: (record, selected) => {
        console.log('onSelect ==> ', record, selected);
        // this.setState({ selectedRows });
      },
      onSelectAll: (selected, selectedRows, changeRows) => {
        console.log('onSelectAll ==> ', selected, selectedRows, changeRows);
        let selectedRowKeys = [];
        if (selected) {
          selectedRowKeys = selectedRows.map(row => row.key);
        }
        this.setState({ selectedRows, selectedRowKeys });
      },
      selectedRowKeys: this.state.selectedRowKeys,
    };

    if (this.state.columns && this.state.columns.length > 0) {
      // console.log('Search[data] ===> ', this.state.filters);
      const { prefixCls } = this.props;
      const listContainer = `${prefixCls}-container`;
      console.log(this.state.selectedRows);
      return (
        <div className={prefixCls}>
          <ToolBar
            prefixCls={prefixCls}
            filters={this.state.filters}
            requestFilterFields={this.state.requestFilterFields}
            onSearch={this._onFilterChange}
            renderTopButtons={this._renderTopButtons}
            toolBarType={this.state.selectedRows && this.state.selectedRows.length > 0}
            isModal={this.props.isModalInput || this.props.isModal}
            isProcess={isProcess}
            isInfo={this.props.isInfo}
            modalCallback={this.props.modalCallback}
            selectRows={this.state.selectedRows.length}
          />
          <div className={listContainer}>
            <div className="loading-mask" style={{ display: this.state.isLoading ? 'inline' : 'none', opacity: 0.5, backgroundColor: '#fff' }} />
            <Table
              shouldScrollToTop={this.shouldScrollToTop}
              locale={{ emptyText: '无符合条件的相关数据' }}
              rowSelection={rowSelection}
              columns={this.state.columns}
              dataSource={this.state.dataSource}
              sortOrder={false}
              pagination={this.state.pagination}
              onChange={this._onChange}
              onRowClick={this._onRowClick}
              prefixCls="mx-table-self"
              isModal={this.props.isModal}
              refStr={this.props.refStr}
            />
          </div>
        </div>
      );
    }
    console.error('template list', 'columns is null!');
    return (<div />);
  }

  @autobind
  menuClick(m) {
    this.setState({
      requestParamsBean: Object.assign({}, this.state.requestParamsBean, { menu: m.menuCode }),
    }, () => {
      this._onSearch();
    });
  }

  getSideMenu() {
    if (isApply(this.props.domainLink)) {
      return processMenu.apply;
    }
    return processMenu.review;
  }

  componentDidMount() {
    if ((!this.state.dataSource || this.state.dataSource.length === 0) && this.props.dataSource.emptyListPrompt) {
      Modal.error({
        title: '提示',
        content: (<ContentRender message={this.props.dataSource.emptyListPrompt} />)
      });
    }
  }

  componentDidUpdate() {
    this.shouldScrollToTop = false;
  }

  render() {
    const main = this.renderList((this.isApply || this.isReview) && this.props.domainType !== PAGE_TYPE_SUMMARY_LIST);
    if ((this.isApply || this.isReview) && this.props.domainType !== PAGE_TYPE_SUMMARY_LIST) {
      setTimeout(() => {
        if (this.props.switchNavBar) {
          this.props.switchNavBar(false);
        }
      });
      const menu = this.getSideMenu(this.props.domainLink);
      this.tag = getMenuItemByFunc(m => m.isSelected === true, menu) || {};
      return (
        <div className="info-container">
          <div className="info-sidebar">
            <SideMenu
              menu={menu}
              menuClick={this.menuClick}
              selectedItem={this.tag}
            />
          </div>
          <div className="main-grid">
            <div className="main_grid_middlle" style={{ height: '100%', backgroundColor: '#e6e9f0' }}>
              {main}
            </div>
          </div>
        </div>
      );
    }
    return main;
  }
}

export default ListView;
