import React from 'react';
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'
import { Renderer, RendererProps } from '../factory';
import { BaseSchema } from '../Schema';
import Record from '../components/record';
import { ActionType } from '../components/record/type'
import { ActionEnum } from '../components/record/enum'
import type { NavType, DataItemType } from '../components/record';
import { tokenize } from '../utils/tpl-builtin'



/**
 * 记录渲染器
 */
export interface RecordSchema extends BaseSchema {
  /**
   * 指定为活动记录
   */
  type: 'record',

  /**
   * 标题
   */
  title?: string,

  /**
   * 导航列表
   */
  nav: Array<NavType>
  
  // 是否开启排序
  isSort?: boolean,

  // 组件高度 默认不传是取父级高度
  height?:string,

  // 是否显示头部
  showHead?: boolean

  // 开启聊天
  enableChat?: boolean

  // 默认数据列表
  initApi?: string

  // sse监听动态数据
  watchApi?: string

  // 评论和回复接口
  commentApi?: string

  // 编辑评论接口
  editCommentApi?: string

  // 删除评论接口
  delCommentApi?: string
}


export interface RecordProps
  extends RendererProps,
    Omit<RecordSchema, 'type' | 'className'> {
  enableChat: boolean,
  showHead: boolean,
  isSort: boolean,
  primaryFieldKey: string
  primaryFieldValue: string
  baseURL: string
  fetcher: (api: any, data?: any, options?: any) => any// 请求接口
}

interface RecordState{
  data: Array<DataItemType>
  loading: boolean,
  
}

export default  class RecordLog extends React.Component<RecordProps, RecordState> {
  static propsList: Array<string> = [];
  message: Array<DataItemType>
  sse: any
  static defaultProps = {
    nav: [],
    enableChat: true,
    showHead: true,
    isSort: true,
  };

  recordRef: any = null;
  constructor(props: RecordProps){
    super(props)
    this.state = {
      data: [],
      loading: props.initApi? true: false,
    }

    this.message = []// this.state.data的中间 过程数据
  }

  static getDerivedStateFromProps(){
    return null
  }

  shouldComponentUpdate(){
    return true
  }

  componentDidMount(){
    this.props.initApi && this.fetchData()
    this.props.watchApi && this.initWatch()
  }

  componentWillUnmount(){
    this.recordRef = null;
  }

  async fetchData(){
    let { initApi, fetcher, primaryFieldKey, primaryFieldValue } = this.props;
    this.setState({
      loading: true
    })
    let json = await fetcher(initApi!, {
      [primaryFieldKey]: primaryFieldValue
    })
    if (json.ok && Array.isArray(json.data)) {
      this.message = json.data
      this.setState({
        data: json.data,
        loading: false
      }, () => {
        this.recordRef.handleScrollToBottom()
      })
    }else{
      this.setState({loading: false})
    }
  }

  initWatch(){
    let { watchApi, baseURL, primaryFieldKey, primaryFieldValue } = this.props;
    
    if(typeof EventSource === 'function'){
      this.sse && this.sse?.close()

      if(baseURL === '/'){
        baseURL = location.origin
      }
      let sseApi = tokenize((baseURL || '') + watchApi!, {
        [primaryFieldKey]: primaryFieldValue
      })

      this.sse = new EventSource(sseApi);

      this.sse.onmessage = (e: any) => {
        let msgObj: DataItemType | null = null
        if(e.data === '连接成功')return console.log('sse connection succeeded!');
        try{
          msgObj = JSON.parse(e.data)
        }catch(e){
          console.log('sse msg type error! ', e.data)
        }

        if(msgObj){
          let be = this.message.filter(v=> msgObj.id && v.id === msgObj.id )
          if(be.length){// 修改消息
            this.message.splice(this.message.indexOf(be[0]), 1, msgObj)
          }else{// 新增消息
            this.message.push(msgObj)
          }

          this.setState({
            data: this.message
          }, () => {
            !be.length && (
              this.recordRef.handleScrollToBottom(msgObj.type)
            )
          })
        }
      }
    }
  }

  delComment = async (id: string): Promise<any> => {
    let { delCommentApi, fetcher } = this.props;

    
    if(!delCommentApi) return null

    const json = await fetcher(delCommentApi, {MSG_ID: id})

    if(!json.ok){
      // 提示 json.msg
    }

  }

  onAction = async (actionData: ActionType): Promise<any> => {
    let { type, id, content } = actionData;
    let { commentApi, editCommentApi, fetcher, onAction, primaryFieldKey, primaryFieldValue} = this.props;

    if(type === ActionEnum.del){
      onAction(null, {
        actionType: "dialog",
        dialog: {
          body: "确定要删除此评论吗？",
          title: "删除评论",
          actions: [
            {
              "type": "button",
              "actionType": "close",
              "label": "取消",
            },
            {
              "type": "button",
              "actionType": "confirm",
              onClick: () => {
                this.delComment(id!)
              },
              "label": "确认",
              level: 'danger'
            },
          ],
        }
      }, {})
      return null
    }

    let data: any = null
    let api: string = ''
    if(type === ActionEnum.comment || type === ActionEnum.reply){
      api = commentApi!
      data = {
        [primaryFieldKey]: primaryFieldValue,
        MSG_CONTENT: content,
      }
      if(type === ActionEnum.reply){
        data.REPLY_ID = id
      }
    }else if(type === ActionEnum.edit){
      api = editCommentApi!
      data = {
        MSG_ID: id,
        MSG_CONTENT: content
      }
    }

    if(!api) return null

    const json = await fetcher(api, data)

    if(!json.ok){
      // 提示 json.msg
    }else{
      this.recordRef.handleReset()
    }
  }

  render() {

    if(this.state.loading)return <RecordLoading />

    return <Record {...this.props} data={this.state.data} refFn={(ref: any) => {
      this.recordRef = ref
    }} onAction={this.onAction}/>;
  }

  getSnapshotBeforeUpdate(prevProps: RecordProps, prevState: RecordState){
    if(prevProps.primaryFieldValue && (prevProps.primaryFieldValue !== this.props.primaryFieldValue)){
      return true
    }
    return null
  }

  componentDidUpdate(prevProps: RecordProps, prevState: RecordState, snapshot: any){
    if(snapshot){
      prevProps.initApi && this.fetchData()
      prevProps.watchApi && this.initWatch()
    }
  }
}

@Renderer({
  type: 'record'
})
export class RecordRenderer extends RecordLog {}

function RecordLoading(){
  return (
    <div style={{paddingLeft: 10, width: '100%', height: '100%', position: 'relative'}}>
      <SkeletonTheme baseColor="#ebebeb" highlightColor="#f5f5f5">
        <p>
          <Skeleton count={1} width={50} height={20} inline={false}/>
        </p>
        <p>
          <Skeleton count={4} width={30} height={10} inline={true} style={{marginRight: 10}}/>
        </p>
        <p style={{marginTop: 20}}>
          <Skeleton count={1} width={30} height={15} inline={true} style={{marginRight: 10}}/>
          <Skeleton count={1} width={'20%'} height={15} inline={true}/>
        </p>
        <p>
          <Skeleton count={1} width={30} height={15} inline={true} style={{marginRight: 10}}/>
          <Skeleton count={1} width={'70%'} height={15} inline={true}/>
        </p>
        <p>
          <Skeleton count={1} width={30} height={15} inline={true} style={{marginRight: 10}}/>
          <Skeleton count={1} width={'50%'} height={15} inline={true}/>
        </p>
      </SkeletonTheme>
    </div>
  )
}