import React, { useContext, useState, useEffect, useRef } from "react";
import uniqueId from 'lodash/uniqueId';
import { Table, Form, Input, Button, Modal, InputNumber } from "antd";
import './EditTable.less'

const EditableContext = React.createContext();

const EditableRow = ({ index, ...props }) => {
  const [form] = Form.useForm();
  return (
    <Form form={form} component={false}>
      <EditableContext.Provider value={form}>
        <tr {...props} />
      </EditableContext.Provider>
    </Form>
  );
};

const EditableCell = ({
  title,
  editable,
  dataType,
  children,
  dataIndex,
  record,
  handleSave,
  ...restProps
}) => {
  const [editing, setEditing] = useState(false);
  const inputRef = useRef();
  const form = useContext(EditableContext);
  useEffect(() => {
    if (editing) {
      inputRef.current.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({[dataIndex]: record[dataIndex]});
  };

  const save = async e => {
    try {
      const values = await form.validateFields();
      toggleEdit();
      handleSave({ ...record, ...values });
    } catch (errInfo) {
      console.log('Save failed:', errInfo);
    }
  };

  let childNode = children;

  if(editing) {
    if (dataType && dataType === "number") {
      childNode = (
        <Form.Item className="editable-cell-form" name={dataIndex}>
          <InputNumber  ref={inputRef} onPressEnter={save} onBlur={save} />
        </Form.Item>
      )
    } else {
      childNode = (
        <Form.Item className="editable-cell-form" name={dataIndex}>
          <Input ref={inputRef} onPressEnter={save} onBlur={save} />
        </Form.Item>
      )
    }
  } else {
    childNode = (
      <div
        className="editable-cell-value-wrap"
        title={record ? record[dataIndex]: ""}
        onClick={toggleEdit}
      >
        {children}
      </div>
    )
  }

  return <td {...restProps}>{childNode}</td>;
};

const EditableHeaderCell = ({
  column,
  children,
  handleHeaderSave,
  ...restProps
}) => {
  const [editing, setEditing] = useState(false);
  const inputRef = useRef();
  const form = useContext(EditableContext);
  useEffect(() => {
    if (editing) {
      inputRef.current.focus();
    }
  }, [editing]);

  const toggleEdit = () => {
    setEditing(!editing);
    form.setFieldsValue({title: column.title});
  };

  const save = async e => {
    try {
      const values = await form.validateFields();
      toggleEdit();
      handleHeaderSave({ ...column, ...values });
    } catch (errInfo) {
      console.log('Save failed:', errInfo);
    }
  };

  let childNode = children;

  // console.log("column",column)

  childNode = editing ? (
    <Form.Item
      className="editable-cell-form"
      name="title"
    >
      <Input ref={inputRef} onPressEnter={save} onBlur={save} />
    </Form.Item>
  ) : (
    <div
      className="editable-cell-value-wrap"
      onClick={toggleEdit}
      title={column ? column.title: ""}
    >
      {children}
    </div>
  );

  if(column && !column.allowEdit) {
    childNode = (
      <div
        className="editable-cell-value-wrap-y"
      >
        {children}
        {column.dataIndex === "y" && <div className="rightTopLabel small-label">s</div>}
        {column.dataIndex === "y" && <div className="leftBottomLabel small-label">x</div>}
      </div>
    )
  }

  return <td {...restProps}>{childNode}</td>;
};

export default class EditTable extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      modalVisible: false,
      tableColumns: [],
      tableDataSource: [],
      modalTableYScale: 500,
    };
    this.CONSTANT = {
      DEFAULT_COL_ATTR: {
        width: 100,
        allowEdit: true
      },
      TABLE_COL_BASE: 's',
      TABLE_ROW_BASE: 'x',
    }
  }

  static getDerivedStateFromProps(nextProps) {
    const {editTableColumns, editTableDataSource, needInitTableData, setNotNeedInitTableData} = nextProps;
    if (needInitTableData) {
      setNotNeedInitTableData();
      return {
        tableColumns:editTableColumns,
        tableDataSource: editTableDataSource,
      };
    }
    return null;
  }

  handleChangeRadioDataType (e) {
    this.setState({
      dataType: e.target.value,
    });
  }

  handleChangeEditTableSource() {
    const { handleChangeEditTable } = this.props;
    const { tableColumns, tableDataSource } = this.state;
    handleChangeEditTable(tableColumns, tableDataSource);
  }

  handleSave(row) {
    const newData = [...this.state.tableDataSource];
    const index = newData.findIndex(item => row.key === item.key);
    const item = newData[index];
    newData.splice(index, 1, { ...item, ...row });
    this.setState({
      tableDataSource: newData,
    });
  };

  handleHeaderSave(column) {
    const tableColumns = [...this.state.tableColumns];
    const newData = tableColumns.map(col => {
      if(col.dataIndex === column.dataIndex) {
        col.title = column.title
      }
      return col;
    })
    this.setState({
      tableColumns: newData,
    });
  };

  getAllRowTitle() {
    const {tableColumns} = this.state;
    const keys = tableColumns.map(col=> col.title);
    return keys;
  }

  getAllColumnTitle() {
    const {tableDataSource} = this.state;
    const keys = tableDataSource.map(col=> col.y);
    return keys;
  }

  getUnusedName(nameBase, isColumn) {
    let usedKeys = [];
    const reg = new RegExp(nameBase, 'i');
    const nameCopyList = [];
    
    if(isColumn) {
      usedKeys = this.getAllColumnTitle();
    } else {
      usedKeys = this.getAllRowTitle();
    }

    usedKeys.forEach(key=>{
      if(typeof(key) === "string" && key.match(reg)) {
        const nameCopy = key.replace(nameBase,"");
        nameCopyList.push(nameCopy);
      }
    })

    let copy = 1;
    for(let index = 1; index <= nameCopyList.length + 1; index += 1) {
      if(nameCopyList.indexOf(`${index}`) === -1) {
        copy = index;
        break;
      }
    }
    const nameResult = `${nameBase}${copy}`
    return nameResult;
  }

  scrollToTableBottom (isModal) {
    let domContainer = document.getElementById("style-container");
    if (isModal) {
      domContainer = document.getElementById("style-container-data-modal");
    }
    const domTable = domContainer.getElementsByClassName("ant-table-body")[0];
    console.log("scrollToTableBottom",domTable.scrollHeight);
    $(domTable).animate({scrollTop: domTable.scrollHeight},500);
  }

  scrollToTableLeft (isModal) {
    let domContainer = document.getElementById("style-container");
    if (isModal) {
      domContainer = document.getElementById("style-container-data-modal");
    }
    const domTable = domContainer.getElementsByClassName("ant-table-body")[0];
    $(domTable).animate({scrollLeft: $(domTable).offset().left},500);
  }

  handleClickAddRow(isModal) {
    const {tableColumns, tableDataSource} = this.state;
    let newId = uniqueId();
    const newRow =  {};
    tableColumns.forEach(col => {
      if(col.type !== "number") {
        newRow[col.dataIndex] = '';
        if(col.dataIndex === 'y') {
          newRow[col.dataIndex] = this.getUnusedName(this.CONSTANT.TABLE_ROW_BASE,true);
        } 
      }
    });
    newRow.key = newId;
    const newDataSource = [...tableDataSource];
    newDataSource.push(newRow);
    this.setState({
      tableDataSource: newDataSource,
    },()=>{
      this.scrollToTableBottom(isModal);
    });
  }

  handleClickAddColumn (isModal) {
    const {tableColumns} = this.state;
    const newColumn = {...this.CONSTANT.DEFAULT_COL_ATTR};
    let newId = uniqueId();
    newColumn.title = this.getUnusedName(this.CONSTANT.TABLE_COL_BASE,false);
    newColumn.dataIndex = newId;
    newColumn.key = newId;
    const newTableColumns = [...tableColumns];
    newTableColumns.push(newColumn);
    this.setState({tableColumns: newTableColumns},()=>{
      this.scrollToTableLeft(isModal);
    });
  }

  handleClickFullScreen () {
    this.setState({modalVisible: true},()=>{
      setTimeout(()=>{
        const modalDom = document.getElementsByClassName("editTableModal")[0];
        if(modalDom) {
          const bodyDom = modalDom.getElementsByClassName("ant-modal-body")[0];
          if(bodyDom) {
            const modalTableYScale = bodyDom.offsetHeight - 100;
            this.setState({modalTableYScale})
          }
        }
      },0)
    });
  }

  handleCancel () {
    this.setState({modalVisible: false});
  };

  render() {
    const {tableColumns, tableDataSource, modalVisible, modalTableYScale} = this.state;
    const components = {
      header: {
        row: EditableRow,
        cell: EditableHeaderCell
      },
      body: {
        row: EditableRow,
        cell: EditableCell,
      },
    };
    const columns = tableColumns.map(col => {
      // if (!col.editable) {
      //   return col;
      // }

      return {
        ...col,
        onHeaderCell: column => ({
          column,
          handleHeaderSave: this.handleHeaderSave.bind(this)
        }),
        onCell: record => ({
          record,
          dataIndex: col.dataIndex,
          title: col.title,
          dataType: col.type,
          handleSave: this.handleSave.bind(this),
        }),
      };
    });
    return (
      <React.Fragment>
        <Table
          className="edit-table"
          components={components}
          dataSource={tableDataSource}
          columns={columns}
          pagination={false}
          bordered
          scroll={{ y: 350 }}
        ></Table>
        <Button type="ghost" className="add-btn add-btn-row" onClick={this.handleClickAddRow.bind(this,false)}>+</Button>
        <Button type="ghost" className="add-btn add-btn-column" onClick={this.handleClickAddColumn.bind(this,false)}>+</Button>
        <Button type="ghost" className="add-btn full-srceen-btn" onClick={this.handleClickFullScreen.bind(this)}>
          <div className="button-label-containter">
            <svg className="svg-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4622"><path d="M592.044 512l177.598 177.598 72.039-72.04c9.005-9.505 23.013-12.006 35.02-7.004 11.507 5.003 19.511 16.51 19.511 29.517l0 224.123c0 17.51-14.508 32.018-32.018 32.018L640.07 896.212c-13.007 0-24.514-8.004-29.517-20.011-5.002-11.507-2.501-25.515 7.004-34.52l72.04-72.039L512 592.044 334.402 769.642l72.04 72.039c9.505 9.005 12.007 23.013 7.004 34.52-5.002 12.007-16.509 20.011-29.516 20.011L159.807 896.212c-17.51 0-32.018-14.508-32.018-32.018L127.789 640.07c0-13.007 8.004-24.514 20.011-29.517 11.506-5.002 25.514-2.501 34.519 7.004l72.04 72.04L431.956 512 254.358 334.402l-72.04 72.04c-6.003 6.003-14.007 9.505-22.512 9.505-4.002 0-8.505-1-12.007-2.501-12.006-5.002-20.011-16.509-20.011-29.516L127.788 159.807c0-17.51 14.508-32.018 32.018-32.018L383.93 127.789c13.007 0 24.514 8.004 29.516 20.011 5.003 11.507 2.501 25.514-7.004 34.519l-72.04 72.04L512 431.956l177.598-177.598-72.04-72.04c-9.505-9.005-12.006-23.012-7.004-34.519 5.003-12.006 16.51-20.011 29.517-20.011l224.123 0c17.51 0 32.018 14.508 32.018 32.018L896.212 383.93c0 13.007-8.004 24.514-19.511 29.516-4.002 1.501-8.505 2.501-12.507 2.501-8.505 0-16.509-3.502-22.513-9.505l-72.039-72.04L592.044 512z" p-id="4623"></path></svg>
            <span>全屏显示</span>
          </div>
        </Button>
        <Modal
          title="编辑静态数据"
          visible={modalVisible}
          maskClosable={false}
          onCancel={this.handleCancel.bind(this)}
          destroyOnClose
          centered
          className="editTableModal"
          footer={null}
        >
          <div className="editTableModalContent">
            <Table
              id="style-container-data-modal"
              className="edit-table"
              components={components}
              dataSource={tableDataSource}
              columns={columns}
              pagination={false}
              bordered
              scroll={{ y: modalTableYScale }}
            ></Table>
            <Button type="ghost" className="add-btn add-btn-row" onClick={this.handleClickAddRow.bind(this,true)}>+</Button>
            <Button type="ghost" className="add-btn add-btn-column" onClick={this.handleClickAddColumn.bind(this,true)}>+</Button>
          </div>
        </Modal>
      </React.Fragment>    
    )
  }
}
