/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { ImageKnifeOptionV2 } from '../model/ImageKnifeOption';
import { ImageKnifeRequest, ImageKnifeRequestState } from '../model/ImageKnifeRequest';
import common from '@ohos.app.ability.common';
import { ImageKnife } from '../ImageKnife';
import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData';
import { IEngineKey } from '../key/IEngineKey';
import { DefaultEngineKey } from '../key/DefaultEngineKey';
import { emitter } from '@kit.BasicServicesKit';
import { taskpool } from '@kit.ArkTS';

@ComponentV2
export struct ImageKnifeComponentV2 {
  @Local pixelMap: PixelMap | string | Resource | ImageContent | undefined = ImageContent.EMPTY
  @Param syncLoad: boolean = false
  @Local adaptiveWidth: Length = '100%'
  @Local adaptiveHeight: Length | undefined = '100%'
  @Local objectFit: ImageFit = ImageFit.Contain
  private componentId: number = 0
  private request: ImageKnifeRequest | undefined
  private lastWidth: number = 0
  private lastHeight: number = 0
  private currentWidth: number = 0
  private isImageFitAutoResize: boolean = false
  private currentHeight: number = 0
  private componentVersion: number = 0
  private currentContext: common.UIAbilityContext | undefined = undefined
  private lastOption?: string
  @Param @Require imageKnifeOption: ImageKnifeOptionV2
  @Monitor('imageKnifeOption','imageKnifeOption.loadSrc','imageKnifeOption.signature','imageKnifeOption.transformation','imageKnifeOption.downsampleOf')
  watchImageKnifeOption() {
    if (this.lastOption !== undefined && this.lastOption === this.getChangeValue() && this.pixelMap !== ImageContent.EMPTY) {
      return
    }
    this.lastOption = this.getChangeValue()
    this.clearLastRequest()
    this.componentVersion++
    this.isImageFitAutoResize = false
    this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
    LogUtil.log('watchImageKnifeOption execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
      ' loadSrc = ' + this.imageKnifeOption.loadSrc +
      ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
      ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
      ' componentId = ' + this.componentId)
    ImageKnife.getInstance().execute(this.getRequest(
      this.currentWidth, this.currentHeight, this.componentId))
  }

  getChangeValue() {
    if (typeof (this.imageKnifeOption.loadSrc as PixelMap)?.isEditable === 'boolean') {
      return
    }
    return `${JSON.stringify(this.imageKnifeOption.loadSrc)},${this.imageKnifeOption.signature},
            ${this.imageKnifeOption.downsampleOf},${JSON.stringify(this.imageKnifeOption.transformation)},
            ${JSON.stringify(this.imageKnifeOption.dynamicRangeMode)}`
  }
  aboutToAppear(): void {
    this.lastOption = this.getChangeValue()
    this.objectFit =
      this.imageKnifeOption.placeholderObjectFit ?? (this.imageKnifeOption.objectFit ?? ImageFit.Contain)
    this.adaptiveHeight = this.objectFit === ImageFit.Auto ? undefined : this.adaptiveHeight
    this.componentId = this.getUniqueId()
    if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题,建议使用同步方式在aboutToAppear时加载图片
      let engineKey: IEngineKey = new DefaultEngineKey();
      let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
        .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
      if (memoryCacheSrc !== undefined){
        LogUtil.log('aboutToAppear success load loadSrc from memory cache for loadSrc = '+ this.imageKnifeOption.loadSrc)
        this.pixelMap = memoryCacheSrc.source;
      }else{
        LogUtil.log('aboutToAppear fail load loadSrc from memory cache for loadSrc = '+ this.imageKnifeOption.loadSrc)
        if (this.imageKnifeOption.placeholderSrc !== undefined){
          let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance()
            .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption))
          if (memoryCachePlace !== undefined){
            LogUtil.log('aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = ' + this.imageKnifeOption.placeholderSrc)
            this.pixelMap = memoryCachePlace.source;
          }else{
            LogUtil.log('aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = ' + this.imageKnifeOption.placeholderSrc)
          }
        }
      }
    }
  }

  aboutToDisappear(): void {
    this.emitterDestroy()
    this.clearLastRequest()
  }

  aboutToRecycle() {
    this.pixelMap = ImageContent.EMPTY
    this.emitterDestroy()
    this.clearLastRequest()
  }

  emitterDestroy() {
    if (typeof this.request?.imageKnifeOption.loadSrc === 'string' && !this.request?.drawMainSuccess) {
      emitter.emit(this.request.imageKnifeOption.loadSrc + this.componentId)
    }
  }
  /**
   * 对已DESTROY的组件不再发起请求
   */
  private clearLastRequest(){
    if (this.request !== undefined) {
      this.request.requestState = ImageKnifeRequestState.DESTROY
      if (this.request.taskRequest !== undefined && !this.request.taskRequest.isDone()) {
        taskpool.cancel(this.request.taskRequest)
      }
      this.request.destroy()
      this.request = undefined
    }
  }
  build() {
    Image(this.pixelMap)
      .dynamicRangeMode(this.imageKnifeOption.dynamicRangeMode)
      .colorFilter(this.imageKnifeOption.drawingColorFilter)
      .objectFit(this.objectFit)
      .width(this.adaptiveWidth)
      .height(this.adaptiveHeight)
      .border(this.imageKnifeOption.border)
      .syncLoad(this.syncLoad)
      .draggable(false)
      .onComplete(this.imageKnifeOption.onComplete)
      .onSizeChange((oldValue:SizeOptions, newValue:SizeOptions) => {
        this.currentWidth = newValue.width as number
        this.currentHeight = newValue.height as number
        this.lastWidth = oldValue.width as number
        this.lastHeight = oldValue.height as number
        if (this.currentWidth <= 0 || (this.objectFit !== ImageFit.Auto && this.currentHeight <= 0)) {
          // 存在宽或者高为0,此次重回无意义,无需进行request请求
        } else {
          // 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同  条件2:当前是第一次绘制
          if (this.currentHeight !== this.lastHeight || this.currentWidth !== this.lastWidth) {
            LogUtil.log('onSizeChange execute request:width=' + this.currentWidth + ' height= ' + this.currentHeight +
              ' loadSrc = ' + this.imageKnifeOption.loadSrc +
              ' placeholderSrc = ' + this.imageKnifeOption.placeholderSrc +
              ' errorholderSrc = ' + this.imageKnifeOption.errorholderSrc +
              ' componentId = ' + this.componentId)

            if (this.objectFit === ImageFit.Auto && this.isImageFitAutoResize) {
              this.isImageFitAutoResize = false
            } else {
              ImageKnife.getInstance().execute(this.getRequest(
                this.currentWidth, this.currentHeight, this.componentId))
            }
          }
        }
      })
  }

  getCurrentContext(): common.UIAbilityContext {
    if (this.currentContext === undefined) {
      this.currentContext = this.getUIContext().getHostContext() as common.UIAbilityContext
    }
    return this.currentContext
  }

  getRequest(width: number, height: number,componentId: number): ImageKnifeRequest {
    this.request = new ImageKnifeRequest(
      this.imageKnifeOption,
      this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
      this.getUIContext().vp2px(width),
      this.getUIContext().vp2px(height),
      this.componentVersion,
      {
        showPixelMap: (version: number, pixelMap: PixelMap | string | Resource, requestSource: ImageKnifeRequestSource,size?:Size) => {
          if (version !== this.componentVersion) {
            return //针对reuse场景,不显示历史图片
          }
          this.pixelMap = pixelMap
          LogUtil.info('image load showPixelMap:' + this.request?.componentId + ',srcType:' + requestSource +
            ',version:' + this.request?.componentVersion +
            ',size:' + JSON.stringify(size))
          if ((this.imageKnifeOption.objectFit === ImageFit.Auto ||
            this.imageKnifeOption.placeholderObjectFit === ImageFit.Auto ||
            this.imageKnifeOption.errorholderObjectFit === ImageFit.Auto) && this.isImageFitAutoResize === false) {
            this.isImageFitAutoResize = true
          }

          if (requestSource == ImageKnifeRequestSource.SRC) {
            this.objectFit =
              this.imageKnifeOption.objectFit ?? ImageFit.Contain
            this.adaptiveHeight = this.objectFit === ImageFit.Auto ? undefined : '100%'
          } else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
            this.objectFit =
              this.imageKnifeOption.placeholderObjectFit ?? (this.imageKnifeOption.objectFit ?? ImageFit.Contain)
            this.adaptiveHeight = this.objectFit === ImageFit.Auto ? undefined : '100%'
          } else {
            this.objectFit =
              this.imageKnifeOption.errorholderObjectFit ?? (this.imageKnifeOption.objectFit ?? ImageFit.Contain)
            this.adaptiveHeight = this.objectFit === ImageFit.Auto ? undefined : '100%'
          }
        }
      },
      componentId
    )
    return this.request
  }
}