/**
 * 移动端九宫格组件
 */
import { Input, message } from "antd";
import React from "react";
import { Renderer, RendererProps } from '../factory';
import { getHashCode } from "../utils/utils";
import iconMap from '../icons/font';
import { isMobile, isVisible, qsstringify } from "../utils/helper";
import { isNil } from "lodash";
import { ActionSchema } from "../renderers/Action";
import { BadgeSchema } from "../components/Badge";
import { IScopedContext, ScopedContext } from "../Scoped";
import { ServiceStore } from "../store/service";

interface MatrixProps extends RendererProps {
  type: 'matrix',
  items: MatrixItem[],
  className: string
  showSearch: boolean
  columnNum: number
}
interface MatrixItem {
  icon: string,
  title: string,
  color?: string,
  bgColor?: string,
  body: any,
  hiddenOn?: string,
  hidden?: boolean,
  name?: string
  clickAction?: ActionSchema;
  badge?: BadgeSchema;
}
interface MatrixState {
  searchValue: string,
  filterItems: MatrixItem[],
  targetElement: boolean,
  defaultKey?: string | number
}
class Matrix extends React.Component<MatrixProps, MatrixState> {
  Ref: any; //Aug
  constructor(props: MatrixProps) {
    super(props)
    let activeKey: any = undefined;
    const tabs = props.items;
    const collectedActiveTab = sessionStorage.getItem('collectedActiveTab')
    if (!isNil(collectedActiveTab)) {
      const collectedContent = JSON.parse(collectedActiveTab)
      let keyList = collectedContent.keyList as Array<string | number>
      if (keyList.length) {
        const targetKey = keyList.pop()
        //这里需要处理name不存在的情况，因为name是新加的，这是为了兼容之前收藏的节点
        if (isNil(tabs[0].name)) {
          if (typeof targetKey == 'number' && tabs[targetKey]) {
            //name不存在且收藏的是下标，那就只能设置当前的key了，这是兼容以前收藏的节点
            activeKey = targetKey
          } else {
            message.info('该节点不存在，请检查是否已被删除')
            keyList = []
          }
        } else {
          //如果查询到了，说明是使用tabName收藏
          const targetIndex = tabs.findIndex(item => item.name === targetKey)
          if (targetIndex === -1) {
            //这里判断tabName没有定位到的情况，要么是被删除，要么是使用下标进行收藏
            if (typeof targetKey == 'number' && tabs[targetKey]) {
              //说明定位成功
              if (tabs[targetKey].name === collectedContent.itemName) {
                activeKey = targetKey
              } else {
                //顺序改变，导致定位失败，则查找打开相同tabName的tab
                const getIndex = tabs.findIndex(item => item.name === collectedContent.itemName)
                activeKey = getIndex !== -1 ? getIndex : targetKey
              }
            } else {
              message.info('该节点不存在，请检查是否已被删除')
              keyList = []
            }
          } else {
            activeKey = targetIndex
          }
        }
        if (keyList.length > 0) {
          sessionStorage.setItem('collectedActiveTab', JSON.stringify({ ...collectedContent, keyList }))
        } else {
          sessionStorage.removeItem('collectedActiveTab')
        }
      }
    }
    this.state = {
      searchValue: '',
      filterItems: [],
      targetElement: false,
      defaultKey: activeKey
    }
  }

  componentDidMount() {
    const { defaultKey } = this.state
    if (!isNil(defaultKey)) {
      const { items, matrixId } = this.props
      const item = items[defaultKey]
      if (item) {
        const hashNum = getHashCode(item.title) % 54 || 0
        const url = item?.body?.schemaApi?.url
        const hashmatrixId = url ? getHashCode(url).toString() : getHashCode(item.body.name).toString()
        const targetIcon = iconMap[hashNum]
        this.handleClick({ ...item, icon: item.icon || targetIcon.icon, index: defaultKey, matrixId, hashmatrixId }, true)
      }
    }
  }

  componentWillUnmount() {
    const matrixKeyListStr = sessionStorage.getItem('matrixKeyList')
    if (matrixKeyListStr) {
      const matrixKeyList = JSON.parse(matrixKeyListStr) as number[]
      if (matrixKeyList.length > 0) matrixKeyList.pop()
      if (matrixKeyList.length > 0) {
        sessionStorage.setItem('matrixKeyList', JSON.stringify(matrixKeyList))
      } else {
        sessionStorage.removeItem('matrixKeyList')
      }
    }
  }

  handleClick = ({ icon, title, body, index, matrixId, hashmatrixId, name }:
    { icon?: string, title: string, body: any, index: number, matrixId?: boolean, hashmatrixId: string, name?: string },
    defaultSelect?: boolean) => {
    const matrixKeyListStr = sessionStorage.getItem('matrixKeyList')
    if (matrixKeyListStr) {
      const matrixKeyList = JSON.parse(matrixKeyListStr) as Array<string | number>
      matrixKeyList.push(isNil(name) ? index : name)
      sessionStorage.setItem('matrixKeyList', JSON.stringify(matrixKeyList))
    } else {
      sessionStorage.setItem('matrixKeyList', JSON.stringify([isNil(name) ? index : name]))
    }
    const str = sessionStorage.getItem('matrixMap')
    const menuPath = (location.hash.split('#')?.[1] ?? location.hash ?? location.href) + '/' + (matrixId ? hashmatrixId : "Matrix" + hashmatrixId)
    let matrixMap = str ? JSON.parse(str) : {}
    let newKeyList: Array<number> | undefined = undefined
    const nodeList = menuPath.split('/')
    if (!nodeList[nodeList.length - 1].includes('Matrix')) {
      const newNodeList = [...nodeList]
      newNodeList.pop()
      const prevMenuPath = newNodeList.join('/')
      const prevTabItem = matrixMap[prevMenuPath]
      if (prevTabItem?.keyList?.length > 0) {
        newKeyList = [isNil(name) ? index : name, ...prevTabItem.keyList]
      }
    }
    const currentTabItem = {
      pageTitle: title,
      icon: icon,
      schemaApi: body.schemaApi.url,
      appId: sessionStorage.getItem('appId'),
      path: this.props.$path,
      keyList: newKeyList && newKeyList?.length > 0 ? newKeyList : (sessionStorage.getItem('matrixKeyList') ? JSON.parse(sessionStorage.getItem('matrixKeyList') ?? '') : undefined),
      isTab: true,
      title: title,
      tabKey: index,
      tabName: name,
      itemName: name
    }
    matrixMap = {
      ...matrixMap,
      [menuPath]: currentTabItem
    }
    sessionStorage.setItem('matrixMap', JSON.stringify(matrixMap))
    const { env, onPageLink, data } = this.props;
    if (defaultSelect) {
      env?.onPageLink ? env?.onPageLink(matrixId ? hashmatrixId : "Matrix" + hashmatrixId, "Matrix", title, { schema: body }, data)
        : onPageLink?.(matrixId ? hashmatrixId : "Matrix" + hashmatrixId, "Matrix", title, { schema: body }, data)
    }
  }
  onChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    const { items } = this.props;
    const newItems = e.target.value ? items.filter(item => item.title.includes(e.target.value)) : [];
    this.setState({ searchValue: e.target.value, filterItems: newItems });
  }
  contentRef = (ref: any) => {
    const { classnames: cx } = this.props;
    if (ref?.closest(`.${cx('Drawer')}`)) {
      this.setState({ targetElement: true })
    }
    this.Ref = ref
  }

  // 当itemaction触发的时候 subpath query ctx 都会有 走的是this.receive的逻辑
  reload(subpath?: string, query?: any, ctx?: any, isItemAction?: boolean) {
    // 我被触发了
    this.props?.store?.updateData(ctx)
  }
  render() {
    const { items, render, classnames: cx, data, env, matrixId, linkPage, onPageLink, showSearch = true, columnNum } = this.props;
    const { searchValue, filterItems, targetElement } = this.state;
    const len = filterItems.length || (items?.length ?? 0);
    const clearBot = len - (len % 4 || 4) - 1;

    return (
      <div className={cx('Matrix-container')} ref={this.contentRef}>
        {showSearch && items.length > 12 && (
          <div className={cx('Matrix-Search')}>
            <Input placeholder="搜索模板名称" value={searchValue} onChange={this.onChange} />
          </div>
        )}
        <div className={cx('Matrix-group')}>
          {
            (filterItems.length ? filterItems : items)?.map((item, index) => {
              const hashNum = getHashCode(item.title) % 54 || 0
              const url = item?.body?.schemaApi?.url
              const hashmatrixId = url ? getHashCode(url).toString() : getHashCode(item.body.name).toString()
              const targetIcon = iconMap[hashNum]
              const { icon = targetIcon.icon, name, title, hiddenOn, hidden, body, color = '#fff', bgColor = '#6599ef' } = item;
              const martrixBody = [
                {
                  type: 'icon',
                  icon,
                  color,
                  bgColor,
                  badge: item.badge ? { ...item.badge, offset: [0, 10] } : undefined
                },
                {
                  type: 'tpl',
                  tpl: title
                },
              ]
              return <div
                onClick={() => this.handleClick({ icon, title, body, index, matrixId, hashmatrixId, name })}
                className={cx('Matrix-item', { 'clear-bot': index > clearBot, hidden: hidden || (hiddenOn && !isVisible({ hiddenOn }, data)) })} key={index}
                style={{ width: columnNum ? `${100 / (columnNum <= 0 ? 4 : columnNum)}%` : undefined }}
              >
                {
                  (!linkPage && !targetElement && (env?.onPageLink || onPageLink)) ? render('action',
                    {
                      type: 'action',
                      body: martrixBody,
                    },
                    {
                      className: 'matrix-action',
                      onClick: () => {
                        if (isMobile()) {
                          env?.onPageLink ? env?.onPageLink(matrixId ? hashmatrixId : "Matrix" + hashmatrixId, "Matrix", title, { schema: body }, data)
                            : onPageLink?.(matrixId ? hashmatrixId : "Matrix" + hashmatrixId, "Matrix", title, { schema: body }, data)
                        } else {
                          env.onPageLink?.(item.name ?? getHashCode(item.title).toString(), item.name ?? '', item.title, { schema: item.body }, null)
                        }
                      }
                    }
                  )
                    :
                    item.clickAction ? render('clickAction', { ...item.clickAction, type: 'action', body: martrixBody }, { className: 'matrix-action' }) : render('action', { type: 'action', actionType: 'drawer', body: martrixBody, drawer: { title, body, actions: null, } }, { className: 'matrix-action' })
                }
              </div>
            })
          }
        </div>
      </div >
    )
  }
}

@Renderer({
  type: 'matrix',
  storeType: ServiceStore.name,
})
export class MatrixRenderer extends Matrix {
  static contextType = ScopedContext;

  constructor(props: MatrixProps, context: IScopedContext) {
    super(props);
    const scoped = context;
    scoped.registerComponent(this);
  }

  componentWillUnmount() {
    super.componentWillUnmount();
    const scoped = this.context as IScopedContext;
    scoped.unRegisterComponent(this);
  }

  reload(subpath?: string, query?: any, ctx?: any, isItemAction?: boolean) {
    const scoped = this.context as IScopedContext;
    if (subpath) {
      return scoped.reload(
        query ? `${subpath}?${qsstringify(query)}` : subpath,
        ctx
      );
    }
    return super.reload(subpath, query, ctx, isItemAction);
  }

}