
import React, { useEffect, useState } from 'react';
import moment from 'moment';
import { Tag, Popover, Table, Drawer, Modal } from 'antd';
import Icon from '@/components/icons';
import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import findIndex from 'lodash/findIndex';
import { fields2columns } from '../SortableTable';
import ViewFactory from '..';
import './style.less';
import { getImageByUrl, testUrl } from '@/components/form.fields';
import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
import marked from 'marked';
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css';

marked.setOptions({
  gfm: true,
  breaks: true,
});

const InterfaceTypes = new Map<string, any>();

function registerFieldComponent(type, Component) {
  InterfaceTypes.set(type, Component);
}

function registerFieldComponents(components) {
  Object.keys(components).forEach(key => {
    registerFieldComponent(key, components[key]);
  });
}

function getFieldComponent(type) {
  if (InterfaceTypes.has(type)) {
    return InterfaceTypes.get(type);
  }
  return InterfaceTypes.get('string');
}

export function StringField(props: any) {
  const { value, viewType } = props;
  if (!value) {
    return null;
  }
  if (typeof value === 'object') {
    return JSON.stringify(value);
  }
  if (viewType === 'table' && value.length > 20) {
    return (
      <Popover content={<div onClick={(e) => {
        e.stopPropagation();
      }} style={{maxWidth: 300}}>{value}</div>}>{value.substring(0, 15)}...</Popover>
    );
  }
  return (
    <>{value}</>
  );
}

export function TextareaField(props: any) {
  const { value, viewType } = props;
  if (!value) {
    return null;
  }
  if (viewType !== 'table') {
    return <div className={'textarea-field-content'} style={{maxWidth: 300}} dangerouslySetInnerHTML={{__html: marked(value)}}/>;
  }
  if (value.length > 20) {
    return (
      <Popover content={(
        <div onClick={(e) => e.stopPropagation()} className={'textarea-field-content'} style={{maxWidth: 300}} dangerouslySetInnerHTML={{__html: marked(value)}}/>
      )}>{value.substring(0, 15)}...</Popover>
    );
  }
  return (
    <>{value}</>
  );
}

export function BooleanField(props: any) {
  const { value } = props;
  return (
    <>{value ? <CheckOutlined style={{color: '#52c41a'}}/> : <CloseOutlined style={{color: '#f5222d'}}/>}</>
  );
}

export function NumberField(props: any) {
  const { schema: { precision = 0 }, value } = props;
  if (!isNumber(value)) {
    return null;
  }
  return (
    <div className={'number-field'}>{new Intl.NumberFormat().format(value)}</div>
  );
}

export function isNumber(num) {
  if (typeof num === 'number') {
    return num - num === 0;
  }
  if (typeof num === 'string' && num.trim() !== '') {
    return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
  }
  return false;
};

export function PercentField(props: any) {
  const { schema: { precision = 0 }, value } = props;
  if (!isNumber(value)) {
    return null;
  }
  return (
    <div className={'percent-field'}>{new Intl.NumberFormat().format(value)}%</div>
  );
}

export function DateTimeField(props: any) {
  const { schema: { dateFormat, showTime, timeFormat }, value } = props;
  const m = moment(value);
  if (!m.isValid()) {
    return null;
  }
  let format = dateFormat;
  if (showTime) {
    format += ` ${timeFormat}`;
  }
  return (
    <>{m.format(`${format}`)}</>
  );
}

export function IconField(props) {
  const { value } = props;
  return <Icon type={value}/>;
}

function toFlat(items = []): Array<any> {
  let flat = [];
  items.forEach(item => {
    flat.push(item);
    if (Array.isArray(item.children) && item.children.length) {
      flat = flat.concat(toFlat(item.children));
    }
  });
  return flat;
}

export function DataSourceField(props: any) {
  const { schema: { dataSource = [] }, value } = props;
  const items = toFlat(dataSource);
  // console.log(items);
  if (isEmpty(value)) {
    return null;
  }
  if (Array.isArray(value)) {
    return value.map(val => {
      const item = items.find(item => item.value === val);
      return (
        <Tag color={item.color}>
          {item ? item.label : val}
        </Tag>
      )
    });
  }
  const item = items.find(item => item.value === value);
  return (
    <Tag color={item.color}>
      {item ? item.label : value}
    </Tag>
  )
}

export function RealtionField(props: any) {
  const { schema: { labelField }, value } = props;
  if (!value) {
    return null;
  }
  const items = Array.isArray(value) ? value : [value];
  return (
    <>
      {items.map(item => (
        <span>{get(item, labelField)}</span>
      ))}
    </>
  );
}

export function SubTableField(props: any) {
  const { schema: { children }, value } = props;
  console.log(value);
  if (!Array.isArray(value)) {
    return null;
  }
  return (
    <div className={'sub-table-field'}>
      <Table size={'small'} columns={fields2columns(children)} dataSource={value} pagination={false}/>
    </div>
  );
}

export function LinkToField(props: any) {
  const { schema, value } = props;
  if (!value) {
    return null;
  }
  const values = Array.isArray(value) ? value : [value];
  return (
    <div className={'link-to-field'}>
      {values.map(item => <LinkToFieldLink data={item} schema={schema}/>)}
    </div>
  );
}

export function LinkToFieldLink(props) {
  const { data, schema, schema: { title, labelField } } = props;
  const [visible, setVisible] = useState(false);
  // console.log(schema);
  return (
    <span className={'link-to-field-tag'}>
      <a onClick={(e) => {
        e.stopPropagation();
        setVisible(true);
      }}>{data[labelField]}</a>
      <Drawer 
        // @ts-ignore
        onClick={(e) => {
          e.stopPropagation();
        }}
        className={'noco-drawer'}
        bodyStyle={{padding: 0}} 
        width={'40%'}
        title={`查看${title}详情`}
        visible={visible}
        onClose={() => setVisible(false)}
      >
        <ViewFactory
          resourceName={schema.target}
          viewName={'details'}
          resourceKey={data.id}
        />
      </Drawer>
    </span>
  );
}

function getImgUrls(value) {
  const values = Array.isArray(value) ? value : [value];
  return values.filter(item => testUrl(item.url, {
    exclude: ['.png', '.jpg', '.jpeg', '.gif']
  })).map(item => item);
}

export function AttachmentField(props: any) {
  const { value, schema } = props;
  const [imgIndex, setImgIndex] = useState(0);
  const [visible, setVisible] = useState(false);
  if (!value) {
    return null;
  }
  const values = Array.isArray(value) ? value : [value];
  const images = getImgUrls(values);
  console.log(images);
  return (
    <div onClick={(e) => {
      e.stopPropagation();
    }} className={'attachment-field'}>
      {values.map(item => <AttachmentFieldItem onClick={() => {
        setVisible(true);
        const index = findIndex(images, img => item.id === img.id);
        setImgIndex(index);
      }} data={item} schema={schema}/>)}
      {visible && <Lightbox
        mainSrc={get(images, [imgIndex, 'url'])}
        nextSrc={get(images, [imgIndex + 1, 'url'])}
        prevSrc={get(images, [imgIndex - 1, 'url'])}
        onCloseRequest={() => setVisible(false)}
        onMovePrevRequest={() => {
          setImgIndex((imgIndex + images.length - 1) % images.length);
        }}
        onMoveNextRequest={() => {
          setImgIndex((imgIndex + 1) % images.length);
        }}
      />}
    </div>
  );
}

export function AttachmentFieldItem(props: any) {
  const { title, url } = props.data || {};
  const img = getImageByUrl(url, {
    exclude: ['.png', '.jpg', '.jpeg', '.gif']
  })
  // const [visible, setVisible] = useState(false);
  return (
    <>
      <a onClick={(e) => {
        e.stopPropagation();
        if (testUrl(url, {
          exclude: ['.png', '.jpg', '.jpeg', '.gif']
        })) {
          props.onClick && props.onClick();
          // setVisible(true);
          e.preventDefault();
        }
      }} className={'attachment-field-item'} target={'_blank'} href={url}>
        <img height={20} alt={title} title={title} src={`${img}?x-oss-process=style/thumbnail`}/>
      </a>
      {/* <Modal
          className={'attachment-modal'}
          onCancel={(e) => {
            e.stopPropagation();
            setVisible(false);
          }}
          // @ts-ignore
          onClick={(e) => {
            e.stopPropagation();
          }}
          bodyStyle={{padding: 0}}
          footer={null}
          visible={visible}>
          <img onClick={(e) => {
            e.stopPropagation();
          }} style={{height: 'auto', width: '100%'}} alt={title} title={title} src={url}/>
        </Modal> */}
    </>
  );
}

registerFieldComponents({
  string: StringField,
  textarea: TextareaField,
  boolean: BooleanField,
  select: DataSourceField,
  multipleSelect: DataSourceField,
  radio: DataSourceField,
  checkboxes: DataSourceField,
  number: NumberField,
  percent: PercentField,
  datetime: DateTimeField,
  createdAt: DateTimeField,
  updatedAt: DateTimeField,
  icon: IconField,
  createdBy: RealtionField,
  updatedBy: RealtionField,
  subTable: SubTableField,
  linkTo: LinkToField,
  attachment: AttachmentField,
});

export default function Field(props: any) {
  const { schema = {} } = props;
  const Component = getFieldComponent(schema.interface);
  return <Component {...props}/>;
}
