import React, { useImperativeHandle, useRef, useEffect, useCallback, useState, useMemo } from 'react'

const itemSize = 40;

const Table = React.forwardRef((props, ref) => {
  const {columns = [], mainKey = 'id', autoNext = true, pageFinished, dataSource} = props;

  const sizeRef = useRef();
  const tableRef = useRef();

  const [pageSize, setPageSize] = useState(0);
  const [page, setPage] = useState(1);

  const [data, setData] = useState([])

  const totalPage = useMemo(
    () => Math.ceil(data.length / pageSize), 
    [data, pageSize]
  );

  const currentData = useMemo(
    () => data.slice(pageSize * (page - 1), pageSize * page), 
    [data, pageSize, page]
  )

  const tableSetting = useCallback(() => {
    let { offsetHeight, scrollHeight, offsetWidth, scrollWidth } = tableRef.current;
    let pageSize = Math.floor(offsetHeight / itemSize) - 1;
    setPageSize(pageSize);
  }, [])

  const nextPage = useCallback(() => {
    if(page + 1 > totalPage){
      if(autoNext){
        setPage(1);
      }else{
        pageFinished && pageFinished();
      }
    }else{
      setPage(page + 1);
    }
  }, [totalPage, page])

  useEffect(() => {
    let innerWindow = sizeRef.current.contentDocument.defaultView;
    innerWindow.addEventListener("resize", tableSetting);
    tableSetting();
    return () => {
      innerWindow.removeEventListener("resize", tableSetting);
    }
  }, [tableSetting])

  useEffect(() => {
    if (dataSource) { 
      setData(dataSource);
      setPage(1);
    }
  }, [dataSource]);

  useImperativeHandle(ref, () => ({
    nextPage,
    setData: data => {
      setData(data);
      setPage(1);
    },
    addData: addData => {
      setData(data.concat(...addData))
    },
    updateData: updateData => {
      setData(data.map(item => {
        let mainValue = item[mainKey];
        let update = updateData.find(i => i[mainKey] === mainValue);
        if(update) item = update;
        return item;
      }))
    },
    deleteData: deleteData => {
      setData(data.filter(item => {
        let mainValue = item[mainKey];
        return !deleteData.find(i => i[mainKey] === mainValue);
      }))
    },
  }), [data, nextPage, mainKey])

  return (
    <div className="screen-table" ref={tableRef}>
      <object
        ref={sizeRef}
        tabIndex="-1"
        type="text/html"
        aria-hidden="true"
        data="about:blank"
        style={{
          display: "block",
          position: "absolute",
          top: 0,
          left: 0,
          width: "100%",
          height: "100%",
          border: "none",
          padding: 0,
          margin: 0,
          opacity: 0,
          zIndex: -1000,
          pointerEvents: "none",
        }}>
      </object>
      <table>
        <thead>
          <tr>
            {columns.map(({title, width}) => {
              let thProps = {key: title};
              if(width !== undefined) thProps.style = {width: width + 'px'}
              return <th {...thProps}>{title}</th>
            })}
          </tr>
        </thead>
        <tbody>
          {currentData.map((item, index) => (
            <tr key={item[mainKey]} className={index % 2 === 1 ? `delay-${index} stripe`: `delay-${index}`}>
              {columns.map(config => {
                let {title,code, render} = config;
                if(render) return <td key={title}>{render(item[code], config, item)}</td>;
                return <td key={title}>{item[code]}</td>
              })}
            </tr>
          ))}
        </tbody>
      </table>
      <style jsx>{`
        .screen-table{
          height: 100%;
          overflow: hidden;
          text-align: center;
          position: relative;
        }
        .screen-table > table{
          width: 100%;
        }
        .screen-table th,
        .screen-table td{
          height: ${itemSize}px;
          word-break: break-all;
          color: rgba(255, 255, 255, 0.85);
          font-weight: 400;
        }
        .screen-table th{
          background: rgba(40, 163, 255, 0.25);
        }
        .screen-table .stripe td{
          background: rgba(40, 163, 255, 0.1);
        }
        .screen-table tbody tr{
          animation-name: show;
          animation-duration: 0.3s;
          animation-iteration-count: 1;
          opacity: 0;
          animation-fill-mode: forwards;
        }
        @keyframes show {
          from {opacity: 0;}
          to {opacity: 1;}
        }
      `}</style>
      <style jsx global>{`
        .delay-0{ animation-delay: 0s; }
        .delay-1{ animation-delay: 0.2s; }
        .delay-2{ animation-delay: 0.4s; }
        .delay-3{ animation-delay: 0.6s; }
        .delay-4{ animation-delay: 0.8s; }
        .delay-5{ animation-delay: 1s; }
        .delay-6{ animation-delay: 1.2s; }
        .delay-7{ animation-delay: 1.4s; }
        .delay-8{ animation-delay: 1.6s; }
        .delay-9{ animation-delay: 1.8s; }
      `}</style>
    </div>
  );
})

export default Table;