import { Color, Material, Node, UIRenderer, UITransform, Vec2 } from 'cc'

import ShaderMaterialPrefab from '../../game/prefab/ShaderMaterialPrefab'

export default class ShaderHelper {
  /**
   * 清除所有shader
   * @param showNode
   * @param material
   */
  public static clearAllEffect(
    showNode: Node,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).default,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 设置图片灰白程度
   * @param showNode
   * @param grayLevel
   * @param material
   */
  public static setGrayEffect(
    showNode: Node,
    grayLevel: number = 1,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab)
      .grayMaterial,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      material.setProperty('grayLevel', grayLevel)
      renderComponent.setMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        material.setProperty('grayLevel', grayLevel)
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 播放变灰过程动画
   */
  public static showGrayMv(showNode: Node) {
    let grayValue: number = 0.5
    const intervalId = setInterval(() => {
      grayValue += 0.01
      if (grayValue >= 1) {
        grayValue = 1
        clearInterval(intervalId)
      }
      if (showNode) ShaderHelper.setGrayEffect(showNode, grayValue)
    }, 1)
  }

  /**
   * 设置图片老化
   * @param showNode
   * @param grayLevel
   * @param material
   */
  public static setOldPhotoEffect(
    showNode: Node,
    grayLevel: number = 1,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).oldPhoto,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      material.setProperty('oldLevel', grayLevel)
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        material.setProperty('oldLevel', grayLevel)
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 播放变灰过程动画
   */
  public static showOldPhotoMv(showNode: Node) {
    let grayValue: number = 0
    const intervalId = setInterval(() => {
      grayValue += 0.01
      if (grayValue >= 1) {
        grayValue = 1
        clearInterval(intervalId)
      }
      if (showNode) ShaderHelper.setOldPhotoEffect(showNode, grayValue)
    }, 1)
  }

  /**
   * 增加内发光特效
   * showNode:要增加特效的节点或者他的子节点
   * material:发光特效材质
   * materialParam: {}
   * materialParam.glowColor:cc.v4(r,g,b,a)  颜色rbga值的结构体
   * materialParam.glowColorSize:这里为约束一下值发光宽度值在 [0.0, 0.1] 因为 0.1+ 之后的效果可能不明显，也可以自己尝试修改,个人测试感觉0.01效果最佳
   * materialParam.glowThreshold:这里为约束一下值发光阈值值在 [0.0, 0.5] 因为 0.5+ 之后的效果可能就是其他效果，个人感觉0.1效果最佳
   */
  public static setGlowInner(
    showNode: Node,
    materialParam: any,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).glowInner,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      material.setProperty('glowColor', materialParam.glowColor)
      material.setProperty('glowColorSize', materialParam.glowColorSize)
      material.setProperty('glowThreshold', materialParam.glowThreshold)
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        material.setProperty('glowColor', materialParam.glowColor)
        material.setProperty('glowColorSize', materialParam.glowColorSize)
        material.setProperty('glowThreshold', materialParam.glowThreshold)
        renderComponent.setMaterial(material, 0)
      })
    })
  }

  /**
   * 设置不同颜色的发光
   * @param showNode
   * @param color
   */
  public static setCommonGlowInner(showNode: Node, color: Color = Color.WHITE) {
    this.setGlowInner(showNode, {
      glowColor: color,
      glowColorSize: 0.015,
      glowThreshold: 0.1,
    })
  }

  /**
   * 播放被攻击闪烁过程动画
   */
  public static showFlash(showNode: Node, totalFlashTimes: number = 1) {
    let timeCount: number = 0
    const color: Color = Color.WHITE
    let flashTimes: number = 0
    const intervalId = setInterval(() => {
      timeCount += 1
      if (timeCount % 50 === 0) {
        const tempCount: number = timeCount / 50
        if (tempCount % 2 === 0) {
          color.a = 100
          this.setGlowInner(showNode, {
            glowColor: color,
            glowColorSize: 0.1,
            glowThreshold: 0,
          })
        } else {
          flashTimes++
          this.setGlowInner(showNode, {
            glowColor: color,
            glowColorSize: 0,
            glowThreshold: 0,
          })
          if (flashTimes > totalFlashTimes) clearInterval(intervalId)
        }
      }
    }, 1)
  }

  /**
   * 马赛克
   * @param showNode
   * @param materialParam
   * @param material
   */
  public static setMosaic(
    showNode: Node,
    materialParam: any,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).mosaic,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      material.setProperty('xBlockCount', materialParam.xBlockCount)
      material.setProperty('yBlockCount', materialParam.yBlockCount)
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        material.setProperty('xBlockCount', materialParam.xBlockCount)
        material.setProperty('yBlockCount', materialParam.yBlockCount)
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 播放被攻击闪烁过程动画
   */
  public static showMosaicMv(showNode: Node, callback: Function = null) {
    let masaicTimes: number = 500
    const intervalId = setInterval(() => {
      masaicTimes -= 2
      this.setMosaic(showNode, {
        xBlockCount: masaicTimes,
        yBlockCount: masaicTimes,
      })
      if (masaicTimes <= 30) {
        clearInterval(intervalId)
        if (callback) callback()
      }
    }, 1)
  }

  /**
   * 设置圆角剪切
   * @param showNode
   * @param roundCornerRadius
   * @param material
   */
  public static setRoundCornerCrop(
    showNode: Node,
    roundCornerRadius: number = 0.1,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab)
      .roundCornerCrop,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      // material.setProperty("roundCornerRadius", roundCornerRadius);
      material.setProperty('xRadius', roundCornerRadius)
      material.setProperty('yRadius', roundCornerRadius)
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        // material.setProperty("roundCornerRadius", roundCornerRadius);
        material.setProperty('xRadius', roundCornerRadius)
        material.setProperty('yRadius', roundCornerRadius)
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 设置闪光
   * @param showNode
   * @param lightColor  光颜色
   * @param lightWidth 光的宽度
   * @param lightAngle 光的角度
   * @param enableGradient
   * @param cropAlpha
   * @param enableFog
   * @param material
   */
  public static setFlashLight(
    showNode: Node,
    lightColor: Color,
    lightWidth: number,
    lightAngle: number = 0,
    enableGradient: boolean = true,
    cropAlpha: boolean = true,
    enableFog: boolean = false,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab)
      .flashLight,
  ) {
    // showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
    //   material.setProperty('lightColor', lightColor)
    //   material.setProperty('lightWidth', lightWidth)
    //   material.setProperty('lightAngle', lightAngle)
    //   material.setProperty('enableGradient', enableGradient ? 1 : 0)
    //   material.setProperty('cropAlpha', cropAlpha ? 1 : 0)
    //   material.setProperty('enableFog', enableFog ? 1 : 0)
    //   renderComponent.setSharedMaterial(material, 0)
    // })
    // showNode.children.forEach((childNode) => {
    //   childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
    //     material.setProperty('lightColor', lightColor)
    //     material.setProperty('lightWidth', lightWidth)
    //     material.setProperty('lightAngle', lightAngle)
    //     material.setProperty('enableGradient', enableGradient ? 1 : 0)
    //     material.setProperty('cropAlpha', cropAlpha ? 1 : 0)
    //     material.setProperty('enableFog', enableFog ? 1 : 0)
    //     renderComponent.setSharedMaterial(material, 0)
    //   })
    // })
    const setMaterialProperties = (renderer: UIRenderer) => {
      try {
        material.setProperty('lightColor', lightColor)
        material.setProperty('lightWidth', lightWidth)
        material.setProperty('lightAngle', lightAngle)
        material.setProperty('enableGradient', enableGradient ? 1 : 0)
        material.setProperty('cropAlpha', cropAlpha ? 1 : 0)
        material.setProperty('enableFog', enableFog ? 1 : 0)
        renderer.setSharedMaterial(material, 0)
      } catch (error) {
        console.error('Error setting material properties:', error)
      }
    }
    const renderComponents = [
      ...showNode.getComponents(UIRenderer),
      ...showNode.children.flatMap(childNode => childNode.getComponents(UIRenderer)),
    ]

    renderComponents.forEach((renderComponent: UIRenderer) => {
      setMaterialProperties(renderComponent)
    })
  }

  /**
   * 玩家升级shader动画
   * @param showNode
   * @param callback
   */
  public static showFlashLightMv(showNode: Node, callback: Function = null) {
    const nowClor: Color = new Color(0, 0, 0, 255)
    let colorIndex: number = 0
    let lightAngle: number = 0
    const intervalId = setInterval(() => {
      if (colorIndex === 0) {
        nowClor.r = nowClor.r + 2
        if (nowClor.r >= 255) colorIndex += 1
      } else if (colorIndex === 1) {
        nowClor.g = nowClor.g + 2
        if (nowClor.g >= 255) colorIndex += 1
      } else {
        nowClor.b = nowClor.b + 2
        if (nowClor.b >= 255) {
          clearInterval(intervalId)
          ShaderHelper.clearAllEffect(showNode)
          if (callback) callback()

          return
        }
      }
      lightAngle += 1
      this.setFlashLight(showNode, nowClor, 1, lightAngle)
    }, 1)
  }

  public static setFlag(
    showNode: Node,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).flag,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }

  /**
   * 设置高斯模糊
   * @param showNode
   * @param material
   */
  public static setGaussian(
    showNode: Node,
    material: Material = ShaderMaterialPrefab.instance.getComponent(ShaderMaterialPrefab).gaussian,
  ) {
    showNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
      const tran = renderComponent.node.getComponent(UITransform)
      material.setProperty('textureSize', new Vec2(tran.contentSize.width, tran.contentSize.height))
      renderComponent.setSharedMaterial(material, 0)
    })
    showNode.children.forEach((childNode) => {
      childNode.getComponents(UIRenderer).forEach((renderComponent: UIRenderer) => {
        const tran = renderComponent.node.getComponent(UITransform)
        material.setProperty(
          'textureSize',
          new Vec2(tran.contentSize.width, tran.contentSize.height),
        )
        // material.setProperty("textureSize", cc.v2(showNode.width, showNode.height));
        renderComponent.setSharedMaterial(material, 0)
      })
    })
  }
}
