import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { ListView, PullToRefresh, } from 'antd-mobile';
import LoadingComponent from './LoadingComponent';
import styles from './ListViewDiy.less';

const makeCancelable = (promise) => {
  let canceled = false;
  return {
    cancel: () => canceled = true,
    promise: (...args) => new Promise((resolve, reject) => {
      promise(...args).then(res => {
        if (!canceled) {
          resolve(res);
        } else {
          reject(res)
        }
      }).catch(e => {
        reject(e);
      })
    }),
  }

};

//  封装的listView组件，展示分页后的数据，可以下拉刷新，滚动到底部请求数据，传递搜索条件刷新。
//  props:
//    request: 请求方法, params => promise 接受查询条件为参数，返回一个promise，promise.resolve()的值是接口返回的response
//    renderRow: ListView组件的renderRow,
//    searchValues: 搜索条件
//    pageSize, 每页显示多少条数据
//    mountedSearch: 页面加载后是否查询
//    ListSeparator: ListView组件的ListSeparator
//    NoResult: 搜索结果为空时显示的内容
//    responseCallback: 搜索结果回调函数
export class ListViewDiy extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoading: false, // 管理footer组件里面的loading状态, 只有滚动到底部加载数据时才为ture, 不覆盖旧数据
      isRefreshing: false, // pullToRefresh组件的loading状态，只有搜索和下拉刷新时为true，覆盖旧数据
      listViewData: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      dataSource: [],
      hasSearched: false, //  是否已经搜索过，
      ...this.defaultPagination(),
    }
  }

  static LoadingMore = 'LoadingMore';
  static RefreshData = 'RefreshData'

  componentDidMount() {
    if (this.props.mountedSearch) {
      this.queryData();
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.searchValues !== this.props.searchValues) {
      this.queryData();
    }
  }

  defaultPagination = () => ({
    pageNo: 1,
    pageSize: this.props.pageSize,
    total: 1,
    hasNextPage: true,
  })

  queryData = (isRefresh = true) => {
    const { searchValues, responseCallback, } = this.props;
    const { isLoading, isRefreshing, hasNextPage, pageSize, pageNo, } = this.state;

    if (isLoading || isRefreshing || (!isRefresh && !hasNextPage)) return;

    // 如果是刷新数据，只改变pullToRefresh组件的loading状态，否则改变footer的loading状态
    this.setState({[isRefresh ? 'isRefreshing' : 'isLoading']: true });

    const params = {
      pageNo: isRefresh ? 1 : pageNo,
      pageSize,
      ...searchValues,
    };
    this.cancelableRequest = makeCancelable(this.props.request);

    this.cancelableRequest.promise(params).then(res => {
      this.setState({ hasSearched: true, })
      if (res) {
        const { rows, pageNo, pageSize, hasNextPage, } = res;
        this.setState(({ dataSource, listViewData, }) => {
          const ds = isRefresh ? rows : dataSource.concat(rows);
          return {
            dataSource: ds,
            listViewData: listViewData.cloneWithRows(ds),
            pageNo,
            pageSize,
            hasNextPage,
          };
        });
        responseCallback && responseCallback(res,)
      }
    }).finally(() => {
      this.setState({ isLoading: false, isRefreshing: false, });
    });
  }

  onEndReached = (event) => {
    this.setState(({ pageNo }) => ({ pageNo: pageNo + 1}), () => this.queryData(false));
  }

  componentWillUnmount() {
    if (this.cancelableRequest) {
      this.cancelableRequest.cancel();
    }
  }


  render() {
    const { listViewData, isLoading, isRefreshing, hasSearched, dataSource, } = this.state;
    const { renderRow, ListSeparator, pageSize = 10, NoResult, renderHeader } = this.props;
    const renderFooter = () => {
      if (!hasSearched) return null;
      if (!dataSource.length) return NoResult;
      return <LoadingComponent isLoading={isLoading} />
    }
    return (
      <div className={styles.listWrapper}>
        <ListView
          ref={el => this.lv = el}
          dataSource={listViewData}
          renderHeader={renderHeader}
          renderFooter={renderFooter}
          renderRow={(rowData, sectionID, rowID, highlightRow) => renderRow(
            rowData, sectionID, rowID, highlightRow, this.queryData,
          )}
          renderSeparator={ListSeparator}
          scrollRenderAheadDistance={500}
          onEndReached={this.onEndReached}
          pullToRefresh={<PullToRefresh
            refreshing={isRefreshing}
            onRefresh={this.queryData}
          />}
          pageSize={pageSize}
          initialListSize={pageSize}
          onEndReachedThreshold={10}
          contentContainerStyle={{height: '100%', width: '100%'}}
          style={{
            height: '100%',
            overflow: 'scroll',
          }}
        />
      </div>
    );
  }
}

export default ListViewDiy;
