import { RNComponentContext, RNViewBase } from '@rnoh/react-native-openharmony';
import { RNC } from "./generated/ts"
import testNapi from 'libglnative.so'
import { emitter } from '@kit.BasicServicesKit';
import { JSON } from '@kit.ArkTS';
import { fileIo as fs } from '@kit.CoreFileKit';
import { http } from '@kit.NetworkKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { image } from '@kit.ImageKit';
import { resourceManager } from '@kit.LocalizationKit';

// 声明 Native 模块接口
interface ContextChecker {
  isContextLost(): boolean;

  releaseContext(): void;
}

interface glObj {
  id: number;
  frag: string;
  name: string
}

interface GlObj {
  data: Array<glObj>
}

interface children {
  shader: number,
  pixelRatio: number,
  via: Array<[]>,
  fboId: number,
  width: number,
  height: number,
  contextChildren: Array<[]>,
  children: Array<children>,
  uniforms: object,
}

interface XComponentContext {
  drawPattern(): void;

  getStatus(): XComponentContextStatus;
};

interface XComponentContextStatus {
  hasDraw: boolean,
  hasChangeColor: boolean,
};
let shaderFlag: boolean = false;

// 重写XComponentController，设置生命周期回调
class MyXComponentController extends XComponentController {
  shaderData1: testNapi.ShaderData = {
    name: 'helloGL', frag:
    'precision highp float;\n' +
      'varying vec2 uv;\n' +
      'void main() {\n' +
      '  gl_FragColor = vec4(uv.x, uv.y, 0.5, 1.0);\n' +
      '}\n'
  }
  shaderData2: testNapi.ShaderData = {
    name: '(gl-react-post)', frag:
    'precision highp float;\n' +
      'varying vec2 uv;\n' +
      'uniform sampler2D t;\n' +
      'void main() {\n' +
      '  gl_FragColor = texture2D(t, uv);\n' +
      '}\n'
  }
  shaderData3: testNapi.ShaderData = {
    name: 'ColoredDisc', frag:
    'precision highp float;\n' +
      'varying vec2 uv;\n' +
      'uniform vec3 fromColor, toColor;\n' +
      'void main() {\n' +
      '  float d = 2.0 * distance(uv, vec2(0.5));\n' +
      '  gl_FragColor = mix(\n' +
      '    vec4(mix(fromColor, toColor, d), 1.0),\n' +
      '    vec4(0.0),\n' +
      '    step(1.0, d)\n' +
      '  );\n' +
      '}\n'
  }
  shaderData4: testNapi.ShaderData = {
    name: 'helloBlue', frag:
    'precision highp float;\n' +
      'varying vec2 uv;\n' +
      'uniform float blue;\n' +
      'void main() {\n' +
      '  gl_FragColor = vec4(uv.x, uv.y, blue, 1.0);\n' +
      '}\n'
  }
  shaderData5: testNapi.ShaderData = {
    name: 'helloBlue', frag:
    'precision highp float;\n' +
      'varying vec2 uv;\n' +
      'uniform sampler2D t;\n' +
      'void main() {\n' +
      '  gl_FragColor = mix(\n' +
      '    texture2D(t, uv),\n' +
      '    vec4(0.0),\n' +
      '    step(0.5, abs(uv.x - 0.5) + abs(uv.y - 0.5))\n' +
      '  );\n' +
      '}\n'
  }
  flag: boolean = true
  surfaceId: string = ''

  onSurfaceCreated(surfaceId: string): void {
    let res = testNapi.CreateSurface(BigInt(surfaceId))
    this.flag = res
    this.surfaceId = surfaceId
    console.log(`#abc onSurfaceCreated surfaceId: ${surfaceId},${res}`)
  }

  onSurfaceChanged(surfaceId: string, rect: SurfaceRect): void {
    console.log(`#abc onSurfaceChanged surfaceId: ${surfaceId}, rect: ${JSON.stringify(rect)}}`)
    // 在onSurfaceChanged中调用ChangeSurface绘制内容
    // testNapi.ChangeSurface(BigInt(surfaceId), rect.surfaceWidth, rect.surfaceHeight)
    console.log(`SetCaptureConfig end`)
  }

  onSurfaceDestroyed(surfaceId: string): void {
    console.log(`#abc onSurfaceDestroyed surfaceId: ${surfaceId}`)
    //testNapi.RemoveShader(BigInt(2))
    // testNapi.DestroySurface(BigInt(surfaceId))
    shaderFlag = false
  }

  getXComponentContext(): Object {
    hilog.error(0x0000, 'testTag', 'getXComponentContext surfaceId = %{public}s', this.surfaceId);
    let context = testNapi.GetContext(BigInt(this.surfaceId))
    if (context) {
      hilog.error(0x0000, 'testTag', 'getXComponentContext context not empty');
    }
    return context
  }
}

export class DownloadUtil {
  async imageUrl(
    context: Context,
    fileName: string,
    fileData: ArrayBuffer
  ) {
    // 2. 获取应用沙箱路径
    const sandboxDir = context.filesDir; // 或 context.cacheDir
    const filePath = `${sandboxDir}/${fileName}`;

    // 3. 写入文件
    const file = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    try {
      await fs.write(file.fd, fileData);
      console.log('File saved to sandbox:', filePath, fileData);
      return filePath; // 返回保存路径
    } finally {
      await fs.close(file.fd);
    }
  }

  /**
   * 下载文件并保存到应用私有目录
   * @param url 文件网络路径
   * @param context UIAbility上下文
   * @param fileName 自定义文件名（带后缀，如 "image.jpg"）
   */
  async downloadAndSaveToSandbox(
    url: string,
    context: Context,
    fileName: string
  ): Promise<string> {
    try {
      const pattern = /^(https?|ftp):\/\/|^\\\\/i;
      if (pattern.test(url)) {
        // 1. 下载文件
        const httpClient = http.createHttp();
        const response = await httpClient.request(url, {
          method: http.RequestMethod.GET,
          expectDataType: http.HttpDataType.ARRAY_BUFFER
        });

        if (response.responseCode !== 200) {
          throw new Error(`HTTP Error: ${response.responseCode}`);
        }

        const fileData = response.result as ArrayBuffer;
        if (!fileData) {
          throw new Error('Downloaded data is empty');
        }
        return this.imageUrl(context, fileName, fileData)
      } else {
        const resMgr = context.resourceManager;
        const rawFile =
          await resMgr.getRawFileContent(url.replace('asset://','assets/'));
        const buffer = rawFile.buffer.slice(0);
        return this.imageUrl(context, fileName, buffer)
      }
    } catch (error) {
      console.error('Download or save failed:', JSON.stringify(error));
      throw new Error("Download failed");
    }
  }
}

@Component
export struct RNCGLCanvas {
  public static readonly NAME = RNC.RNCGLCanvas.NAME
  public ctx!: RNComponentContext
  public tag: number = 0
  private eventEmitter: RNC.RNCGLCanvas.EventEmitter | undefined = undefined
  private appContext: Context = getContext(this);
  private cleanUpCallbacks: (() => void)[] = [];
  // 组件的状态包装器
  @State private descriptorWrapper: RNC.RNCGLCanvas.DescriptorWrapper =
    {} as RNC.RNCGLCanvas.DescriptorWrapper
  // 存储需要在组件卸载时清理的回调函数
  @State errorMessage: string = '';
  @State contextStatus: string = '正常';
  @State getContextFlag: boolean = true;
  @State onLoadErrorFlag: boolean = true;
  @State xComponentContext: XComponentContext | undefined = undefined;
  @State fileArr: Array<string> = ['']
  private xComponentController: MyXComponentController = new MyXComponentController();
  private DownloadUtil: DownloadUtil = new DownloadUtil()

  aboutToAppear() {
    // 创建EventEmitter实例，用于处理事件的订阅和触发
    this.eventEmitter = new RNC.RNCGLCanvas.EventEmitter(this.ctx.rnInstance, this.tag)
    this.onDescriptorWrapperChange(this.ctx.descriptorRegistry.findDescriptorWrapperByTag<RNC.RNCGLCanvas.DescriptorWrapper>(this.tag)!)
    // 订阅组件状态的变化，然后放入cleanUpCallbacks等待清理
    console.info('#abc aboutToAppear')
    this.cleanUpCallbacks.push(this.ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag,
      (_descriptor, newDescriptorWrapper) => {
        // 更新组件状态
        this.onDescriptorWrapperChange(newDescriptorWrapper! as RNC.RNCGLCanvas.DescriptorWrapper)
      }
    ))
  }

  onChangData() {
    console.info('555666', this.xComponentController.flag)
    if (this.xComponentController.flag) {
      this.onChang()
    } else {
      if (this.onLoadErrorFlag) {
        this.ctx.rnInstance.emitDeviceEvent('onLoadError', this.xComponentController.flag);
        this.onLoadErrorFlag = false;
      }
    }
  }

  onChang() {
    const surfaceId = this.xComponentController.getXComponentSurfaceId();
    const addShaderGl = async (item: GlObj) => {
      // 处理每个glObj
      console.info('#abc shader1234', JSON.stringify(item));
      item.data.forEach((itemGl: glObj) => {
        testNapi.AddShader(itemGl.id, {
          name: itemGl.name,
          frag: itemGl.frag
        });
      });

      // 在addShader处理完成后执行后续操作
      if (this.descriptorWrapper.props.uri != undefined && surfaceId != '') {
        await this.getPath(surfaceId); // 等待getPath完成
        this.onSetData(surfaceId); // 直接调用onSetData
      } else {
        this.onSetData(surfaceId);
      }
    }

    emitter.on('addShader', addShaderGl);
    let arr = JSON.parse(this.descriptorWrapper.props.children) as Array<children>
    let glArr: number[] = [];
    arr.forEach(item => {
      console.info('112233', item.shader)
      glArr.push(item.shader)
      item?.children.forEach(glItem => {
        console.info('112233', glItem.shader)
        glArr.push(glItem.shader)
      })
    })
    glArr = glArr.sort((a: number, b: number) => {
      return a - b
    })
    glArr.forEach(item => {
      let objGl = AppStorage.get(item.toString()) as GlObj
      console.info('#abc shader123456', item, JSON.stringify(arr))
      addShaderGl(objGl)
    })
  }

  //更新setData中的数据
  onSetData(surfaceId: string) {
    console.info('shader12345', `${JSON.stringify(this.descriptorWrapper.props.data)}`);
    testNapi.SetData(BigInt(surfaceId), `${JSON.stringify(this.descriptorWrapper.props.data)}`);
    if (this.descriptorWrapper.props.uri != undefined && surfaceId != '') {
      const onProgress = testNapi.OnProgress(BigInt(surfaceId));
      this.ctx.rnInstance.emitDeviceEvent('onProgress', onProgress);
      hilog.error(0x0000, 'testTag', 'Test NAPI OnProgress: count = %{public}d', onProgress.count);
    }
    if (this.getContextFlag) {
      this.getContext();
      this.getContextFlag = false
    }
  }

  getContext() {
    let context = this.xComponentController.getXComponentContext()
    if (context) {
      this.ctx.rnInstance.emitDeviceEvent('onContextRestored', context)
      hilog.error(0x0000, 'testTag1', 'getXComponentContext context not empty')
    } else {
      this.ctx.rnInstance.emitDeviceEvent('onContextLost', context)
    }
  }

  //将网络图片保存在本地
  async getPath(surfaceId:
    string
  ) {
    const timestamp = new Date().toISOString().slice(0, 10).replace(/-/g, ''); // 20250320
    const randomStr = Math.random().toString(36).substring(2, 8); // 6位随机字符串（a-z, 0-9;
    let fileName: string = `${timestamp}_${randomStr}.jpeg`
    let path =
      await this.DownloadUtil.downloadAndSaveToSandbox(this.descriptorWrapper.props.uri as string, this.appContext,
        fileName)
    if (path) {
      this.fileArr.push(path)
    }
    const file = fs.openSync(path, fs.OpenMode.READ_ONLY);
    // 创建图像数据源
    let imageSource = image.createImageSource(file?.fd);
    // 设置解码参数为RGBA_8888
    const decodingOptions: image.DecodingOptions = {
      desiredPixelFormat: 3,
    };
    // 生成PixelMap
    const pixelMap = await imageSource.createPixelMap(decodingOptions);
    const imageInfo = await pixelMap.getImageInfo()
    //获取buffer
    const buffer = new ArrayBuffer(pixelMap.getPixelBytesNumber());
    let imageData: testNapi.ImageData = {
      width: imageInfo.size.width,
      height: imageInfo.size.height,
      path,
      data: buffer
    }
    console.info('iamgeData', path, this.descriptorWrapper.props.uri, JSON.stringify(imageData))
    testNapi.LoadImage(BigInt(surfaceId), this.descriptorWrapper.props.uri, imageData)
    return path
  }

  onDidBuild(): void {
    let time: number = 0
    this.ctx.descriptorRegistry.subscribeToDescriptorChanges(this.tag,
      (_descriptor, newDescriptorWrapper) => {
        if (shaderFlag) {
          this.onChangData()
          console.info('#abc 执行了')
        } else {
          //todo 优化定时器
          console.info('#abc 执行了1')
          time = setTimeout(() => {
            this.onChangData()
          }, 80)
          shaderFlag = true
        }
      })
    this.cleanUpCallbacks.push(() => clearTimeout(time))
  }

  // 更新组件状态
  private onDescriptorWrapperChange(descriptorWrapper: RNC.RNCGLCanvas.DescriptorWrapper) {
    this.descriptorWrapper = descriptorWrapper
  }

  aboutToDisappear() {
    // 执行所有清理回调
    this.cleanUpCallbacks.forEach(cb => cb())
    emitter.off('addShader')
    this.getContextFlag = true
    this.onLoadErrorFlag = true
    this.fileArr.forEach(item=>{
      fs.unlink(item)
    })
  }

  build() {
    RNViewBase({ ctx: this.ctx, tag: this.tag }) {
      Column() {
        XComponent({
          id: 'id_XComponent',
          type: XComponentType.SURFACE,
          controller: this.xComponentController
        })
          .width('100%')
          .height('100%')
          .backgroundColor(this.descriptorWrapper.props.backgroundColor)
          .onLoad(() => {
            this.ctx.rnInstance.emitDeviceEvent('onLoad', { message: 'onLoad' });
          })
          .onAppear(() => {
            // 更新组件状态
            this.onChangData()
          })
      }
    }
  }
}