import MersenneTwister from "./mersenneTwister"
import { ThemeConfig } from "../theme"
import { richTextSupportStyleList } from "../constants/constant"
import merge from 'deepmerge'

// 判断一个颜色是否是白色
export const isWhite = (color: string): boolean => {
  color = String(color).replaceAll(/\s+/g, '')
  return (
    ['#fff', '#ffffff', '#FFF', '#FFFFFF', 'rgb(255,255,255)'].includes(
      color
    ) || /rgba\(255,255,255,[^)]+\)/.test(color)
  )
}

// 判断一个颜色是否是透明
export const isTransparent = (color: string): boolean => {
  color = String(color).replaceAll(/\s+/g, '')
  return (
    ['', 'transparent'].includes(color) || /rgba\(\d+,\d+,\d+,0\)/.test(color)
  )
}

// 从当前主题里获取一个非透明非白色的颜色
export const getVisibleColorFromTheme = (themeConfig: ThemeConfig): string | undefined => {
  const { lineColor, root, second, node } = themeConfig
  const list = [
    lineColor,
    root.fillColor,
    root.color,
    second.fillColor,
    second.color,
    node.fillColor,
    node.color,
    root.borderColor,
    second.borderColor,
    node.borderColor
  ]
  for (let i = 0; i < list.length; i++) {
    const color = list[i]
    if (!isTransparent(color) && !isWhite(color)) {
      return color
    }
  }
  return undefined
}

// 根据内容生成颜色
export const generateColorByContent = (str: string): string => {
  let hash = 0
  for (let i = 0; i < str.length; i++) {
    hash = str.charCodeAt(i) + ((hash << 5) - hash)
  }
  // 这里使用伪随机数的原因是因为
  // 1. 如果字符串的内容差不多，根据hash生产的颜色就比较相近，不好区分，比如v1.1 v1.2，所以需要加入随机数来使得颜色能够区分开
  // 2. 普通的随机数每次数值不一样，就会导致每次新增标签原来的标签颜色就会发生改变，所以加入了这个方法，使得内容不变随机数也不变
  const rng = new MersenneTwister(hash)
  const h = rng.genrand_int32() % 360
  return 'hsla(' + h + ', 50%, 50%, 1)'
}

interface IconItem {
  type: string
  list: Array<{
    name: string
    icon: string
  }>
}

export const mergerIconList = (list: IconItem[]): IconItem[] => {
  return list.reduce((result: IconItem[], item) => {
    const existingItem = result.find(x => x.type === item.type)
    if (existingItem) {
      item.list.forEach(newObj => {
        const existingObj = existingItem.list.find(x => x.name === newObj.name)
        if (existingObj) {
          existingObj.icon = newObj.icon
        } else {
          existingItem.list.push(newObj)
        }
      })
    } else {
      result.push({ ...item })
    }
    return result
  }, [])
}

// 合并主题配置
export const mergeTheme = <T extends object>(dest: T, source: T): T => {
  return merge(dest, source, {
    arrayMerge: (_destinationArray: any[], sourceArray: any[]) => sourceArray
  })
}

interface NodeStyle {
  merge: (prop: string) => string | number
}

interface Node {
  style: NodeStyle
}

// 获取节点实例的文本样式数据
export const getNodeRichTextStyles = (node: Node): Record<string, string> => {
  const res: Record<string, string> = {}
  richTextSupportStyleList.forEach(prop => {
    let value = node.style.merge(prop)
    if (prop === 'fontSize') {
      value = value + 'px'
    }
    res[prop] = String(value)
  })
  return res
}

export interface FontOptions {
  italic?: boolean;
  bold?: boolean;
  fontSize: number;
  fontFamily: string;
}

// 拼接font字符串
export const joinFontStr = ({ italic, bold, fontSize, fontFamily }: FontOptions): string => {
  return `${italic ? 'italic ' : ''} ${bold ? 'bold ' : ''
    } ${fontSize}px ${fontFamily} `
}