import React, { useMemo, useEffect } from 'react';
import { Controlled } from 'react-codemirror2';
import { useState } from 'react';
import { Button, message, Popover, Modal, Dropdown, Menu, Tree, Upload, Spin } from 'antd';
import { saveAs } from 'file-saver';
import styles from './index.less';
import { isDev, useGetRect } from 'editorUtils/tool';
import { EyeOutlined, CodeOutlined, DeleteOutlined, SketchOutlined, DownOutlined, MoreOutlined } from '@ant-design/icons';
import { useHotkeys } from 'react-hotkeys-hook';
import { connect } from 'dva';
import { StateWithHistory } from 'redux-undo';
import PageForm from './PageForm';
import VersionList from './components/VersionList';

require('codemirror/mode/xml/xml');
require('codemirror/mode/javascript/javascript');

const serverUrl = isDev ? 'http://localhost:3000' : 'http://localhost:3000';

const IdeEditor = ({
  location,
  dispatch,
  ideEditor
}) => {

  const { htmlContent, isNewPage, __pageConfig, theme, pageId, pageConfig, previewUrl, assetsData, isLoading, historyData } = ideEditor;
  let siteInfo = localStorage.getItem(`SITE-INFO${SITE_VERSION}`)

  console.log(historyData, '@@@')
  const [isUpdate, setUpdate] = useState(false);
  const [cursor, setCursor] = useState<CodeMirror.Position>({ line: 1, ch: 1 });
  const [data, setData] = useState<{ data: string }>({ data: htmlContent });
  const [doc, setDoc] = useState<any>()
  const [spin, setSpin] = useState<boolean>(false);
  
  useEffect(() => {
    setSpin(isLoading)
  }, [isLoading])

  const handleChange = (
    _editor: CodeMirror.Editor,
    _data: CodeMirror.EditorChange,
    value: string,
  ) => {
    // setData({ data: value });
    dispatch({
      type: 'ideEditor/changeHtmlContent',
      payload: {
        htmlContent: value,
        id: pageId,
        client:theme === 'wap' ? 'wap' : 'pc',
      }
    })
  };

  const onMouseLeaveEvent = () => {
    dispatch({
      type: 'ideEditor/mouseLeaveEventPreview',
      payload: {
        id: pageId,
        client:theme === 'wap' ? 'wap' : 'pc',
      }
    })
  }

  const fetchPage = (_htmlContent) => {
    dispatch({
      type: 'ideEditor/updatePreview',
      payload: {
        id: pageId,
        client:theme === 'wap' ? 'wap' : 'pc',
        html: _htmlContent || htmlContent
      }
    })
  };

  useEffect(function(){
    let timer = setInterval(function() {
      dispatch({
        type: 'ideEditor/mouseLeaveEventPreview',
        payload: {
          id: pageId,
          client:theme === 'wap' ? 'wap' : 'pc',
        }
      })
    }, 10000);
    return () => clearInterval(timer)
  },[])
  const downLoadHtml = () => {
    var file = new File([data.data], `${Date.now()}.html`, { type: 'text/html;charset=utf-8' });
    saveAs(file);
  };

  const onCursorChange = (_editor: CodeMirror.Editor, data1: CodeMirror.Position) => {
    const { line, ch } = data1;
    setCursor({ line, ch });
    setDoc(_editor)
  };

  useHotkeys<HTMLDivElement>(
    'ctrl+s',
    event => {
      fetchPage();
      event.preventDefault();
    },
    [data],
  );

  const editHotKey = useMemo(() => {
    return (editor: CodeMirror.Editor, event: KeyboardEvent) => {
      if (event.ctrlKey && event.key === 's') {
        fetchPage(editor.getValue());
        event.preventDefault();
      }
    };
  }, [fetchPage]);

  const CodeMirrorRender = useMemo(() => {
    return (
      <Controlled
        className={theme === 'wap' ? styles.codeWrap : styles.codePcWrap}
        value={htmlContent}
        options={{
          mode: 'xml',
          theme: 'material',
          lineNumbers: true,
        }}
        onBeforeChange={handleChange}
        cursor={cursor}
        onCursor={onCursorChange}
        onKeyDown={editHotKey}
      />
    );
  }, [cursor, htmlContent, editHotKey]);

  const rect = useGetRect();
  const height = useMemo(() => {
    let res = rect.height - 42 - 1; //-1防止差值产生滚动条
    return res < 694 ? 694 : res;
  }, [rect.height]);

  const phoneHeight = useMemo(() => {
    //let res = rect.height - 42 - 30 - 1; //30是其上边距
    //return res < 694 ? 694 : res;
    return 694; //大屏幕过长，维持高度，需要变高另外处理
  }, []);
  const iframeHeight = useMemo(() => {
    return phoneHeight - 30 - 12 - 12; //上边距30 上下padding 12
  }, [phoneHeight]);


  const onSave = (values, flag) => {
    dispatch({
      type: 'ideEditor/updateState',
      payload: {
        pageConfig: values
      }
    })
    if (flag) {
      dispatch({
        type: 'ideEditor/updateState',
        payload: {
          __pageConfig: values
        }
      })
    }
  }
  const delPage = () => {
    if (!isNewPage) {
      Modal.confirm({
        width: 600,
        title: '删除',
        content: '是否要删除？',
        cancelText: '取消',
        okText: '确认',
        onOk: () => {
          dispatch({
            type: 'ideEditor/delPage',
            payload: {
              type: theme === 'wap' ? 'wap' : 'pc',
              id: pageId
            }
          });
        },
        onCancel() {
          console.log('Cancel');
        },
      })
    } else {
      return false;
    }
  }
  const savePage = () => {
    dispatch({
      type: 'ideEditor/savePage',
      payload: {
        client: theme === 'wap' ? 'wap' : 'pc',
        content: htmlContent,
        html_param: JSON.stringify({
          pageConfig: pageConfig
        }),
        id: pageId,
        param: {
          online_consult: pageConfig?.online_consult,
          sub_status: pageConfig?.sub_status
        },
        sub_status: pageConfig?.sub_status,
        type: 3
      }
    });
  }
  const uploadFile = (file:any) => {
    if (file.file.status === 'done') {
      dispatch({
        type: 'ideEditor/getAssets',
        payload:{
          client:theme === 'wap' ? 'wap' : 'pc',
          page_id: pageId
        }
      })
      setSpin(false)
      message.success('上传成功', 3);
    }else if(file.file.status === 'error'){
      setSpin(false)
      message.error(file.file.response.message, 3);
    }
  }
  const  beforeUpload = (file) => {
    setSpin(true)
    const isLessthan = file.size / 1024 / 1024 < 5
    if (!isLessthan) {
      setSpin(false)
      message.error(`图片大小不能超过${5}MB!`)
    }
    return isLessthan
  }

  const historyDetail = (historyId:string) => {
    dispatch({
      type: 'ideEditor/getPageHistoryDetail',
      payload:{
        id: historyId,
        pageId: pageId,
        client:theme === 'wap' ? 'wap' : 'pc'
      }
    })
  }

  const menu = (
    <Menu>
      <Menu.Item key="1">
        <Upload
            action="/api/cmsAdmin/page/upload/assets"
            onChange={uploadFile}
            showUploadList={false}
            key="upload-file"
            name="file"
            accept=".ico,.jpg,.jpeg,.png,.gif,.bmp,.svg,.webp,.js,.css,.less,.sass,.eot,.otf,.fon,.font,.ttf,.ttc,.woff,.woff2"
            data={{page_id:pageId,client:theme === 'wap' ? 'wap' : 'pc'}}
            headers={{'Site-key':siteInfo}}
            beforeUpload={beforeUpload}
        >
            上传文件
        </Upload>
      </Menu.Item>
      <Menu.Item key="2">
        <Upload
            action="/api/cmsAdmin/page/upload/assets"
            onChange={uploadFile}
            showUploadList={false}
            key="upload-zip"
            name="file"
            accept=".zip"
            data={{page_id:pageId, client: theme === 'wap' ? 'wap' : 'pc'}}
            headers={{'Site-key':siteInfo}}
            beforeUpload={beforeUpload}
        >
            上传ZIP
        </Upload>
      </Menu.Item>
    </Menu>
  );
  const checkSource = (selectedKeys, e) => {
    let node = e.node;
    if(!node.children && doc){
      let str = doc.getLine(cursor.line).substr(cursor.ch, doc.getLine(cursor.line).length)
      let content = '';
      if(node.type == 30){// js代码
        content = `<link rel="stylesheet" type="text/css" href="${node.path}" />`;
      }else if(node.type == 40){ // css代码
        content = `<script type="text/javascript" src="${node.path}"></script>`;
      }else if(node.type == 50){ // css代码
        content = `<img src="${node.path}"/>`;
      }else{
        content = node.path ?? '';
      }
      doc.replaceRange(`${content}${str}`, cursor, {line:cursor.line, ch: doc.getLine(cursor.line).length})
    }
  }
  return (
    <Spin spinning={spin}>
    <div className={styles.wrap}>
      <div className={styles.left} >
        <div className={styles.header}>
            <Dropdown.Button overlay={menu} icon={<MoreOutlined />}
            className={styles.headerButton}
            >静态资源</Dropdown.Button>
        </div>
        <div className={styles.content} >
            <Tree
                showLine
                switcherIcon={<DownOutlined />}
              defaultExpandAll={true}
              onSelect={checkSource}
              treeData={assetsData}
              height={height}
            />
        </div>
        </div>
      <div className={styles.right}>
        <div className={styles.header}>
          <div className={styles.logoArea}>
            <div className={styles.logo} title="LWJ-Editor">
              <a>
                <img style={{ width: 120 }} src='https://static.liweijia.com/liweijia/pc/common/images/logo.svg' alt="LWJ-Editor" />
              </a>
            </div>
            <div className={styles.logoText}>| 在线代码编辑器</div>
          </div>
          <div className={styles.operationBar}>
            <VersionList data={historyData ?? []} onHistory={historyDetail}/>
            {theme === 'wap' && <Button
              type="primary"
              title="保存（ctrl+s）"
              onClick={() => fetchPage()}
              style={{ marginRight: '10px' }}
            >
              <EyeOutlined />
            </Button>}
            <Popover
              placement="bottom" title={'页面配置'} content={<PageForm isNewPage={isNewPage} onSave={onSave} defaultValue={__pageConfig} />} trigger="click">
              <Button type="primary" ghost style={{ marginRight: '12px' }} id="Popover_button">
                <CodeOutlined />
              页面配置
            </Button>
            </Popover>

            <Button type="primary" ghost onClick={delPage} style={{ marginRight: '12px' }}>
              <DeleteOutlined />
              删除页面
            </Button>

            <Button type="primary" ghost onClick={savePage} style={{ marginRight: '12px' }}>
              <SketchOutlined />
            保存页面
          </Button>
          </div>
        </div>
        <div className={styles.contentWrap} style={{ height: `${height}px`, position: 'relative' }}>
          <div onMouseLeave={onMouseLeaveEvent} className={theme === 'wap' ? styles.codeWrap : styles.codePcWrap} style={{ height: `${height}px`, position: 'relative' }}>
            {CodeMirrorRender}
          </div>

          {theme === 'wap' && <div key={previewUrl} className={styles.previewWrap} style={{ height: `${phoneHeight}px` }}>
            <iframe
              title="preview"
              src={previewUrl}
              style={{
                width: '100%',
                height: `${iframeHeight}px`,
                margin: 0,
                padding: 0,
                border: 'none',
              }}
            ></iframe>
          </div>}
        </div>
      </div>
    </div>
    </Spin>
  );
}

export default connect((state: StateWithHistory<any>) => {
  return { ideEditor: state.ideEditor };
})(IdeEditor);
