import React from "react";
import ReactDOM from "react-dom";
import CodeMirror from 'react-codemirror';
import Tabs from "antd/lib/tabs";
import Radio from "antd/lib/radio";
import List from "antd/lib/list";
import Button from "antd/lib/button";
import message from "antd/lib/message";
import 'antd/dist/antd.min.css'
import './rightPanel.less'
import EditTable from './EditTable.jsx'
import EventManager from './EventManager.jsx'
import ScriptManager from './ScriptManager'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/foldgutter.js'
import 'codemirror/addon/fold/brace-fold.js'
import 'codemirror/addon/fold/markdown-fold.js'
import uniqueId from 'lodash/uniqueId';
import papa from 'papaparse';

const { TabPane } = Tabs;
class RightPanelTab extends React.Component {
  constructor(props) {
    super(props);
    this.editor = props.editor;
    this.state = {
      dataType: 1,
      editTableColumns: [
        // { title: 'y', dataIndex: 'y', key: 'y', fixed: 'left', width: 100 },
        // { title: 's1', dataIndex: 's1', key: 's1', width: 100 },
        // { title: 's2', dataIndex: 's2', key: 's2', width: 100 },
        // { title: 's3', dataIndex: 's3', key: 's3', width: 100 },
        // { title: 's4', dataIndex: 's4', key: 's4', width: 100 },
      ],
      editTableDataSource: [
        // { key: "x10", y: "x1",s1: "1", s2: "2", s3: "3"},
        // { key: "x20", y: "x2",s1: "1", s2: "2", s3: "3"},
        // { key: "x3", y: "x3",s1: "1", s2: "2", s3: "3"},
        // { key: "x4", y: "x4",s1: "1", s2: "2", s3: "3"},
        // { key: "x5", y: "x5",s1: "1", s2: "2", s3: "3"},
        // { key: "x6", y: "x6",s1: "1", s2: "2", s3: "3"},
        // { key: "x7", y: "x7",s1: "1", s2: "2", s3: "3"},
        // { key: "x8", y: "x8",s1: "1", s2: "2", s3: "3"},
        // { key: "x9", y: "x9",s1: "1", s2: "2", s3: "3"},
      ],
      staticDataSource: this.props.defaultData,
      dataConfig: this.props.dataConfig,
      needInitTableData: true,
      selectTab: "traits",
    };
    this.CONSTANT = {
      STATIC_DATA: 1,
      REALTIME_DATA: 2,
      INFO_DATA: [
        { field: '字段', value: '说明' },
        { field: 'x', value: '类目' },
        { field: 'y', value: '值' },
        { field: 's', value: '系列(可选)' },
      ],
      DATA_FORMAT_TYPE: {
        RECORDS: 'records',
        ECHART: 'echart'
      },
      TAB_TYPE: {
        TRAITS: 'traits',
        STYLE: 'style',
        DATA: 'data',
        EVENT: 'event'
      },
      DEFAULT_COLUMN_ATTR: {
        editable: true,
        resizable: true,
      }
    }
  }

  componentDidMount() {
    this.setState({
      dataFormatType: this.CONSTANT.DATA_FORMAT_TYPE.ECHART,
    })
  }

  updataComponentDefaultValue(data) {
    const component = self.editor.getSelected();
    const defaultData = component.getTrait('defaultData');
    if (defaultData) {
      defaultData.set('value', JSON.stringify(data).replace(/\"/g, "\\\""))
    }
  }

  setNotNeedInitTableData() {
    this.setState({ needInitTableData: false })
  }

  handleImportData(event) {
    const file = event.target.files[0];
    const { dataConfig } = this.state;
    const reader = new FileReader();
    const { formatDataToTableData } = this;
    reader.readAsText(file, 'utf-8');
    reader.onprogress = function (e) {
      console.log('---- import progress: ', e.loaded);
    }
    reader.onload = function () {
      const str = reader.result;
      const { data } = papa.parse(str);
      console.log('---- import data: ', data);
      formatDataToTableData(data, dataConfig);
    }
  }

  // 当选择的组件变化时，重新初始化数据
  formatDataToTableData = (dataSource, dataConfig) => {
    const { selectTab } = this.state;
    const editTableColumns = [];
    const editTableDataSource = [];
    let dataFormatType = this.CONSTANT.DATA_FORMAT_TYPE.ECHART;
    if (dataSource && (dataSource instanceof Array) && dataSource.length > 0) {
      const data0 = dataSource[0];
      if (data0 instanceof Array) {
        // console.log("数据格式：echarts");
        const headerIdList = [];
        let tableData = [];
        const { dataIncludeHeader, tableColumns } = dataConfig;
        // table header
        if (dataIncludeHeader) {
          const header = dataSource[0];
          tableData = dataSource.slice(1);
          header.forEach((col, index) => {
            var column = {};
            if (index === 0) {
              column = { title: col, dataIndex: 'y', key: 'y', fixed: 'left', width: 100, allowEdit: false }
              headerIdList.push('y')
            } else {
              const newId = uniqueId();
              headerIdList.push(newId)
              column = { title: col, dataIndex: newId, key: newId, width: 100, allowEdit: true }
            }
            editTableColumns.push(column)
          });
        } else {
          tableData = [...dataSource];
          tableColumns.forEach((col, index) => {
            var column = {};
            if (index === 0) {
              column = { title: col.title, dataIndex: 'y', key: 'y', width: 100, type: col.type, allowEdit: false }
              headerIdList.push('y')
            } else {
              const newId = uniqueId();
              headerIdList.push(newId)
              column = { title: col.title, dataIndex: newId, key: newId, width: 100, type: col.type, allowEdit: false };
            }
            editTableColumns.push(column)
          })
        }
        // tableData 数据
        tableData.forEach(data => {
          const newId = uniqueId();
          const newRecord = { key: newId };
          headerIdList.forEach((col, index) => {
            newRecord[col] = data[index];
          })
          editTableDataSource.push(newRecord);
        })
      } else if (data0 instanceof Object) {
        // console.log("数据格式：records");
        dataFormatType = this.CONSTANT.DATA_FORMAT_TYPE.RECORDS;
        const keyMapping = {};
        dataSource.forEach(data => {
          const keys = Object.keys(data);
          keys.forEach(key => {
            if (keyMapping[key] === undefined) {
              keyMapping[key] = uniqueId();
            }
          })
        })
        const allKeys = Object.keys(keyMapping);
        allKeys.forEach(key => {
          const column = { title: key, dataIndex: keyMapping[key], key: keyMapping[key], width: 100 };
          editTableColumns.push(column);
        })
        dataSource.forEach(data => {
          const newId = uniqueId();
          const newRecord = { key: newId };
          allKeys.forEach(key => {
            newRecord[keyMapping[key]] = data[key];
          })
          editTableDataSource.push(newRecord);
        })
      }
    }

    // Tab 无效时切换
    if (dataSource === undefined && selectTab === this.CONSTANT.TAB_TYPE.DATA) {
      this.setState({ selectTab: this.CONSTANT.TAB_TYPE.STYLE, dataType: this.CONSTANT.STATIC_DATA })
    }
    const newDataConfig = { ...dataConfig };
    this.setState({ dataFormatType, editTableColumns, editTableDataSource, staticDataSource: dataSource, needInitTableData: true, dataConfig: newDataConfig }, () => {
      if (this.codeMirrorRef) {
        const codeMirror = this.codeMirrorRef.getCodeMirror();
        const staticDataSourceDisplay = (dataSource !== undefined) ? JSON.stringify(dataSource, null, 2) : '';
        codeMirror.setValue(staticDataSourceDisplay);
      }
    })
  }

  handleChangeSelectTab(activeKey) {
    this.setState({ selectTab: activeKey }, () => {
      if (activeKey === this.CONSTANT.TAB_TYPE.STYLE) {
        if (!this.styleManagerInitialized) {
          const styleManager = this.editor.StyleManager;
          styleManager.postRender();

          this.styleManagerInitialized = true;
        }
      }

      document.querySelectorAll('.gjs-sp-stylemanager-property').forEach(propertyBlock => propertyBlock.removeAttribute('style'))
    });
  }

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

  handleChangeEditTable(editTableColumns, editTableDataSource) {
    this.setState({ editTableColumns, editTableDataSource }, () => {
      this.getFormatStaticDataSource();
    });
  }

  handleClickSaveStaticData() {
    this.editTableRef.handleChangeEditTableSource();
    message.info("保存静态数据");
  }

  getFormatStaticDataSource() {
    const { editTableColumns, editTableDataSource, dataFormatType, dataConfig } = this.state;
    const { dataIncludeHeader } = dataConfig;
    let staticDataSource = [];
    const columns = [...editTableColumns];
    const columnsAvailable = [];
    columns.forEach(col => {
      if (col.title && ((typeof (col.title) === "string" && col.title.trim() !== "") || (typeof (col.title) !== "string"))) {
        columnsAvailable.push(col);
      }
    })

    const datas = [...editTableDataSource];
    if (dataFormatType === this.CONSTANT.DATA_FORMAT_TYPE.RECORDS) {
      let dataKey0 = undefined;
      if (datas.length > 0) {
        dataKey0 = Object.keys(datas[0])[0];
      }
      datas.forEach(data => {
        if (dataKey0 !== undefined && data[dataKey0] !== undefined && data[dataKey0] !== null && ((typeof (data[dataKey0]) === "string" && data[dataKey0].trim() !== "") || (typeof (data[dataKey0]) !== "string"))) {
          const record = {};
          columnsAvailable.forEach(col => {
            record[col.title] = data[col.dataIndex];
          })
          staticDataSource.push(record)
        }
      })
    } else if (dataFormatType === this.CONSTANT.DATA_FORMAT_TYPE.ECHART) {
      // 如果数据是包含header
      if (dataIncludeHeader) {
        const recordHeader = columns.map(col => col.title);
        staticDataSource.push(recordHeader);
      }
      datas.forEach(data => {
        // console.log("data", data.y, typeof(data.y))
        if (data.y !== undefined && data.y !== null && ((typeof (data.y) === "string" && data.y.trim() !== "") || (typeof (data.y) !== "string"))) {
          const record = [];
          columnsAvailable.forEach(col => {
            const value = data[col.dataIndex];
            record.push(value);
          })
          staticDataSource.push(record);
        }
      })
    }

    this.setState({ staticDataSource });
    // 更新组件初始数据
    this.updataComponentDefaultValue(staticDataSource);
  }

  render() {
    const { dataType, editTableColumns, editTableDataSource, staticDataSource, needInitTableData, selectTab, dataConfig } = this.state;
    const staticDataSourceDisplay = (staticDataSource !== undefined) ? JSON.stringify(staticDataSource, null, 2) : '';
    return (
      <div className="rightPanel">
        <Tabs className={`rightPanelContainer ${Boolean(window.appConfig.appReadOnly) ? "readOnly" : ""}`} activeKey={selectTab} onChange={this.handleChangeSelectTab.bind(this)}>
          <TabPane tab="属性" key={this.CONSTANT.TAB_TYPE.TRAITS}>
            <div id="trait-container" className="trait-container panels">
              <div id="traits" className="trait-manager"></div>
            </div>
          </TabPane>
          <TabPane tab="样式" key={this.CONSTANT.TAB_TYPE.STYLE}>
            <div id="style-container" className="style-container panels">
              <div id="styles" className="style-manager"></div>
            </div>
          </TabPane>
          <TabPane tab="数据" key={this.CONSTANT.TAB_TYPE.DATA} disabled={staticDataSource === undefined}>
            <div className="dataType">
              <span className="dataTypeLabel">接入数据类型</span>
              <Radio.Group value={dataType} onChange={this.handleChangeRadioDataType.bind(this)}>
                <Radio value={this.CONSTANT.STATIC_DATA}>静态数据</Radio>
                <Radio value={this.CONSTANT.REALTIME_DATA}>实时数据</Radio>
              </Radio.Group>
            </div>
            <div style={{ display: dataType === this.CONSTANT.STATIC_DATA ? "block" : "none" }}>
              <div className="static-data">
                <div className="static-data-header">
                  <div className="header-flag" />
                  <div className="">编辑静态数据</div>
                  <Button className="header-button" type="primary" size="small">导入CSV文件<input type="file" onChange={this.handleImportData.bind(this)} /></Button>
                  <Button className="header-button" type="primary" size="small" onClick={this.handleClickSaveStaticData.bind(this)}>完成</Button>
                </div>
                <div className="static-data-edit">
                  <EditTable
                    ref={ref => this.editTableRef = ref}
                    editTableColumns={editTableColumns}
                    editTableDataSource={editTableDataSource}
                    needInitTableData={needInitTableData}
                    handleChangeEditTable={this.handleChangeEditTable.bind(this)}
                    setNotNeedInitTableData={this.setNotNeedInitTableData.bind(this)}
                    dataConfig={dataConfig}
                  />
                </div>
              </div>
              <div className="static-data-info">
                <div className="static-data-info-label">说明：列表元素包含以下字段</div>
                <List
                  className="static-data-info-list"
                  itemLayout="horizontal"
                  dataSource={this.CONSTANT.INFO_DATA}
                  renderItem={item => (
                    <List.Item>
                      <div className="info-list-column column-first">{item.field}</div>
                      <div className="info-list-column">{item.value}</div>
                    </List.Item>
                  )}
                />
              </div>
            </div>
            {dataType === this.CONSTANT.REALTIME_DATA && (
              <React.Fragment>
                <div className="static-data">
                  <div className="static-data-header">
                    <div className="header-flag" />
                    <div className="">后面板接受数据格式</div>
                  </div>
                  <div className="static-data-edit">
                    <CodeMirror
                      ref={ref => this.codeMirrorRef = ref}
                      className="code-mirror-container"
                      value={staticDataSourceDisplay}
                      options={{
                        mode: { name: "javascript", json: true },
                        lineNumbers: true,
                        readOnly: 'nocursor',
                        indentUnit: 2,
                        lineWrapping: true, // false->scroll, true-> word-break,
                        foldGutter: true,
                        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
                      }}
                    />
                  </div>
                  <div className="data-label">
                    <svg className="svg-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M872.7 582.6L635.2 177c-53.5-91.3-186.6-88.1-235.6 5.7L187.7 588.3c-46.8 89.7 18.2 197 119.4 197h449.4c104 0 168.8-112.9 116.2-202.7zM496.6 295.2c0-20.5 11.7-31.5 35.1-32.9 22 1.5 33.7 12.5 35.1 32.9V315l-26.4 267.9h-13.2L496.6 315v-19.8z m35.2 406.3c-22-1.5-34.4-13.2-37.3-35.1 1.4-19 13.2-29.3 35.1-30.7 23.4 1.5 36.6 11.7 39.5 30.7-1.5 21.9-13.9 33.6-37.3 35.1z"></path></svg>
                    <span>当前示例数据由静态数据生成</span>
                  </div>
                </div>
              </React.Fragment>
            )}
          </TabPane>
          {/* <TabPane tab="事件" key={this.CONSTANT.TAB_TYPE.EVENT}>
            <ScriptManager />
            <EventManager/>
          </TabPane> */}
        </Tabs>
      </div>
    )
  }
}
export default class RightPanel {
  constructor(editor, opts) {
    _.bindAll(this, [
      "destroy",
      "render",
    ]);

    this.name = "rightPanel";

    this.editor = editor;
    this.c = opts;

    this.styleManagerInitialized = false;

    this.em = editor.getModel();

    editor.on('load', function (component) {
      const traitManager = editor.TraitManager;
      traitManager.postRender();
    });

    const self = this;

    window.ee && window.ee.on('updateReadOnly', () => {
      self.render();
    });

    // 组件移除时，重新渲染
    editor.on('component:remove', function (component) {
      self.render();
    });
    editor.on('component:selected', function (component) {
      if (component.get('type') === 'wrapper') {
        self.render();
        return
      }
      const defaultData = component.attributes.defaultData;
      const defaultDataConfig = component.attributes.defaultDataConfig;

      if (defaultData !== undefined) {
        let renderDataSetting = {};
        if (defaultDataConfig !== undefined) {
          renderDataSetting = JSON.parse(defaultDataConfig.replace(/\\\"/g, "\""));
        }
        const renderData = JSON.parse(defaultData.replace(/\\\"/g, "\""));
        self.render(renderData, renderDataSetting);
      } else {
        self.render();
      }
    });

    const keymaps = editor.Keymaps;
    keymaps.add('ns:my-keymap', 'alt+4', editor => {
      const styleManager = editor.StyleManager;
      const sectors = styleManager.getSectors();
      let hasClosed = false;
      const sectorsLen = sectors.length;
      for (let i = 0; i < sectorsLen; i++) {
        const isOpen = sectors.models[i].get("open");
        if (!isOpen) {
          hasClosed = true;
          break;
        }
      }
      if (hasClosed) {
        sectors.forEach(sector => { sector.set("open", true); })
      } else {
        sectors.forEach(sector => { sector.set("open", false); })
      }
    });
  }

  postRender() {
    this.render();
  }

  render(defaultData, defaultDataConfig) {
    let $rightPanelContainer = document.getElementById("style-container");
    const self = this;

    let dataConfig = {
      dataIncludeHeader: true,
      tableColumns: [],
    };

    if (defaultDataConfig) {
      Object.assign(dataConfig, defaultDataConfig);
    }

    if (this.rightPanelRef) {
      this.rightPanelRef.formatDataToTableData(defaultData, dataConfig);
    } else {
      ReactDOM.render(<RightPanelTab ref={ref => this.rightPanelRef = ref} editor={this.editor} defaultData={defaultData} dataConfig={dataConfig} />, $rightPanelContainer);
    }
    return $rightPanelContainer;
  }

  destroy() { }
}
