/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved.
 * 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 bundleResourceManager from '@ohos.bundle.bundleResourceManager';
import ArkTSUtils from '@arkts.utils';
// import hdsDrawable from '@hms.hds.hdsDrawable';
import image from '@ohos.multimedia.image';
import { BusinessError } from '@ohos.base';
import { LayeredDrawableDescriptor } from '@ohos.arkui.drawableDescriptor';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { ResourceUtil } from '@ohos/settings.common/src/main/ets/utils/ResourceUtil';
import { ThemeManager } from './util/ThemeManager';
import { AppEntry, AppType } from './AppModel';
/* instrument ignore file */
import { AppListLoader } from './AppListLoader';

'use shared'

@Sendable
export class HdsDrawableTools {
  public static readonly defaultSize: number = 48;
  // getHdsIcons,getHdsLayeredIcons最大处理数量为500个
  private static readonly HDS_MAX_PROC_COUNT: number = 500;
  private static instance: HdsDrawableTools = new HdsDrawableTools();
  private readonly TAG: string = 'HdsDrawableTools :';
  private lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock();

  public static getInstance(): HdsDrawableTools {
    return HdsDrawableTools.instance;
  }

  /**
   * 获取Hds裁剪所需的蒙层
   */
  public getMask(): PixelMap {
    let settingsDrawableDescriptor: LayeredDrawableDescriptor =
      bundleResourceManager.getBundleResourceInfo('com.ohos.settings',
        bundleResourceManager.ResourceFlag.GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR)
        .drawableDescriptor as LayeredDrawableDescriptor;
    return settingsDrawableDescriptor.getMask().getPixelMap();
  }

  /**
   * 判断并释放PixelMap
   *
   * @param icon 任意icon对象
   */
  public static releaseIcon(icon: ResourceStr | PixelMap | undefined) {
    if (icon) {
      let procIcon = icon as PixelMap;
      if (procIcon.isEditable !== undefined && procIcon.release !== undefined) {
        procIcon.release();
      }
    }
  }

  /**
   * 获取hds处理的icon
   *
   * @param appEntry 应用信息实例
   * @param drawDesc 要处理的图标描述符
   * @param size 处理后图标输出大小
   * @param mask hds根据该mask进行图标裁剪
   * @param hasBorder 处理图标是否带描边
   * @return 裁剪处理后的图标
   */
  public getCustomHdsIcon(appEntry: AppEntry, drawDesc: DrawableDescriptor, size: number, mask: PixelMap,
    hasBorder: boolean): PixelMap | undefined {
    let result: PixelMap | undefined;
    let fixBundleName = appEntry.name;
    if (appEntry) {
      fixBundleName = this.getFixAppBundleName(appEntry);
    }
    if (drawDesc instanceof LayeredDrawableDescriptor) {
      try {
        // result = hdsDrawable.getHdsLayeredIcon(fixBundleName, drawDesc, size, hasBorder);
      } catch (error) {
        LogUtil.error(`${this.TAG} getHdsLayeredIcon code is ${error?.code}, message is ${error?.message}`);
      }
    } else {
      let pixelMap: PixelMap = drawDesc.getPixelMap();
      try {
        // result = hdsDrawable.getHdsIcon(fixBundleName, pixelMap, size, mask, hasBorder);
      } catch (error) {
        LogUtil.error(`${this.TAG} getHdsIcon code is ${error?.code}, message is ${error?.message}`);
      }
      pixelMap.release();
    }
    if (result) {
      try {
        let imageInfo: image.ImageInfo = result.getImageInfoSync();
        LogUtil.info(`${this.TAG} getCustomHdsIcon name: ${appEntry.name}, pixelMap size {${imageInfo.size.width}, ${imageInfo.size.height}}`);
      } catch {
        LogUtil.error(`${this.TAG} getCustomHdsIcon name: ${appEntry.name}, get imageInfo failed`);
      }
    } else {
      LogUtil.error(`${this.TAG} getCustomHdsIcon name: ${appEntry.name}, get pixelMap failed, it's empty.`);
    }
    return result;
  }

  /**
   * 获取HDS图标接口对应的修正应用包名
   *
   * @param appEntry 应用数据
   */
  public getFixAppBundleName(appEntry: AppEntry): string {
    let fixBundleName = appEntry.name;
    return fixBundleName;
  }

  /**
   * 获取hds批量处理的icons
   *
   * @param bundleName 应用包名
   * @param drawDesc 要处理的图标描述符
   * @param size 处理后图标输出大小
   * @param mask hds根据该mask进行图标裁剪
   * @param hasBorder 处理图标是否带描边
   * @return 裁剪处理后的图标
   */
  public async getCustomHdsIcons(appList: AppEntry[], handleIcons: ESObject, options: ESObject) {
    // 注意:该接口一定要加锁,同一时刻主子线程不能同时执行,否则会报1012600001
    return this.lock_.lockAsync(async () => {
      LogUtil.info(`${this.TAG} getCustomHdsIcons appList len: ${appList.length}, LayeredIcons len: ${handleIcons.layeredIcons.length}, pixelMapIcons len: ${handleIcons.pixelMapIcons.length}`);
      await this.getHdsLayeredIcons(handleIcons.layeredIcons, appList, options);
      await this.getHdsIcons(handleIcons.pixelMapIcons, appList, options);
    }, ArkTSUtils.locks.AsyncLockMode.EXCLUSIVE).catch((error: BusinessError) => {
      LogUtil.error(`${this.TAG} getHdsIcons errcode: ${error?.code}, errMes: ${error?.message}`);
    });
  }

  /**
   * 获取hds批量处理的单层图标
   *
   * @param pixelMapIcons 需要处理的单层图标
   * @param appList 需要更新的应用列表
   * @param options 输出的图标样式
   */
  private async getHdsIcons(pixelMapIcons: ESObject[], appList: AppEntry[], options: ESObject) {
    if (pixelMapIcons.length == 0 || appList.length == 0) {
      LogUtil.error(`${this.TAG} getHdsIcons failed appList: ${appList.length}, pixelMapIcons: ${pixelMapIcons.length}`);
      return;
    }
    LogUtil.info(`${this.TAG} getHdsIcons start appList: ${appList.length}, pixelMapIcons: ${pixelMapIcons.length}`);
    try {
      let remainCount: number = pixelMapIcons.length;
      let handledCount: number = 0;
      let startIndex: number = 0;
      let mask :PixelMap = this.getMask();
      let localMask :PixelMap = this.clonePixelMap(mask);
      mask.release();
      do {
        handledCount = remainCount >= HdsDrawableTools.HDS_MAX_PROC_COUNT ?
          HdsDrawableTools.HDS_MAX_PROC_COUNT : remainCount;
        let handlerIcons: ESObject[] = pixelMapIcons.slice(startIndex, startIndex + handledCount);
        let processedIcons: ESObject[] = []
          // await hdsDrawable?.getHdsIcons(handlerIcons, localMask, options);
        appList.forEach((entryObj: AppEntry) => {
          let icon: ESObject | undefined =
            processedIcons.find((element: ESObject) => {
              return entryObj.name === element.bundleName ||
                entryObj.name === element.bundleName.replace(AppType.CONTAINER_APP, '');
            })
          if (icon) {
            entryObj.icon = icon.pixelMap;
            // try {
            //   let imageInfo: image.ImageInfo = entryObj.icon?.getImageInfoSync()
            //   LogUtil.info(`${this.TAG} getHdsIcons ${entryObj.name} get icon {${imageInfo?.size?.width}, ${imageInfo?.size?.height}} success`);
            // } catch {
            //   LogUtil.error(`${this.TAG} getHdsIcons name: ${entryObj.name}, get imageInfo failed`);
            // }
          }
        })
        startIndex += handledCount;
        handlerIcons.forEach((entryObj:ESObject) => {
          entryObj.pixelMap?.release();
        })
        remainCount -= handledCount;
      } while (remainCount > 0)
      localMask.release();
    } catch (error) {
      LogUtil.error(`${this.TAG} getHdsIcons errcode: ${error?.code}, errMes: ${error?.message}`);
    }
    LogUtil.info(`${this.TAG} getHdsIcons finish appList: ${appList.length}, pixelMapIcons: ${pixelMapIcons.length}`);
  }

  /**
   * 获取hds批量处理的双层图标
   *
   * @param LayeredIcons 需要处理的双层图标
   * @param appList 需要更新的应用列表
   * @param options 输出的图标样式
   */
  private async getHdsLayeredIcons(layeredIcons: ESObject[], appList: AppEntry[],
    options: ESObject) {
    if (layeredIcons.length == 0 || appList.length == 0) {
      LogUtil.error(`${this.TAG} getHdsLayeredIcons failed appList: ${appList.length}, LayeredIcons: ${layeredIcons.length}`);
      return;
    }
    LogUtil.info(`${this.TAG} getHdsLayeredIcons start appList: ${appList.length}, LayeredIcons: ${layeredIcons.length}`);
    try {
      let remainCount: number = layeredIcons.length;
      let handledCount: number = 0;
      let startIndex: number = 0;
      do {
        handledCount = remainCount >= HdsDrawableTools.HDS_MAX_PROC_COUNT ?
        HdsDrawableTools.HDS_MAX_PROC_COUNT : remainCount;
        let handlerIcons: ESObject[] = layeredIcons.slice(startIndex, startIndex + handledCount);
        let processedIcons: ESObject[] = [];
        // let processedIcons: ESObject[] = await hdsDrawable.getHdsLayeredIcons(handlerIcons, options);
        appList.forEach((entryObj: AppEntry) => {
          let icon: ESObject | undefined =
            processedIcons.find((element: ESObject) => {
              return entryObj.name === element.bundleName ||
                entryObj.name === element.bundleName.replace(AppType.CONTAINER_APP, '');
            })
          if (icon) {
            entryObj.icon = icon.pixelMap;
            // try {
            //   let imageInfo: image.ImageInfo = entryObj.icon.getImageInfoSync();
            //   LogUtil.info(`${this.TAG} getHdsLayeredIcons ${entryObj.name} get icon {${imageInfo.size.width}, ${imageInfo.size.height}} success`);
            // } catch {
            //   LogUtil.error(`${this.TAG} getHdsLayeredIcons name: ${entryObj.name}, get imageInfo failed`);
            // }
          }
        })
        startIndex += handledCount;
        remainCount -= handledCount;
      } while (remainCount > 0)
    } catch (error) {
      LogUtil.error(`${this.TAG} getHdsLayeredIcons errcode: ${error?.code}, errMes: ${error?.message}`);
    }
    LogUtil.info(`${this.TAG} getHdsLayeredIcons finish appList: ${appList.length}, LayeredIcons: ${layeredIcons.length}`);
  }

  /**
   * 获取经过hds裁剪的本地资源
   *
   * @param resName 资源名称
   * @param bundleName 应用名称
   * @returns 返回pixelMap,获取失败则返回undefined
   */
  public getHdsIconFromResource(resName: string, bundleName: string): PixelMap | undefined {
    let pixelMap: PixelMap | undefined = ResourceUtil.getPixelMap(resName);
    if (!pixelMap) {
      return undefined;
    }
    let mask: PixelMap = this.getMask();
    let hasBorder: boolean = !ThemeManager.getInstance().checkIsOnlineIcon();
    let result: PixelMap | undefined;
    try {
      // result = hdsDrawable.getHdsIcon(bundleName, pixelMap, HdsDrawableTools.defaultSize,
      //   mask, hasBorder);
    } catch (error) {
      LogUtil.error(`${this.TAG} loadLabelAndIcon getHdsIcon err code: ${error?.code}, message ${error?.message}`);
    }
    pixelMap.release()
    mask.release();
    return result;
  }

  /**
   * 加载指定应用的图标
   *
   * @param appEntry 指定的应用信息
   * @param isHdsHandle 是否需要经过hds处理
   * @return 是否成功加载图标
   */
  public async loadLabelAndIcon(appEntry: AppEntry, isHdsHandle: boolean): Promise<boolean> {
    let defaultLabel: string = appEntry.name;
    let defaultIcon: ResourceStr | PixelMap = AppEntry.getDefaultIcon();

    let bundleFlags = bundleResourceManager.ResourceFlag.GET_RESOURCE_INFO_WITH_LABEL;
    bundleFlags = bundleFlags | (isHdsHandle ?
      bundleResourceManager.ResourceFlag.GET_RESOURCE_INFO_WITH_DRAWABLE_DESCRIPTOR :
      bundleResourceManager.ResourceFlag.GET_RESOURCE_INFO_WITH_ICON);
    let bundleResourceInfo: bundleResourceManager.BundleResourceInfo | undefined =
      appEntry.getBundleResourceInfo(appEntry.name, bundleFlags, appEntry.appIndex);
    if (!bundleResourceInfo || !appEntry.appInfo) {
      appEntry.label = defaultLabel;
      appEntry.icon = defaultIcon;
      LogUtil.error(`${this.TAG} loadLabelAndIcon fail, name: ${appEntry?.name}, appIndex: ${appEntry?.appIndex}`);
      return false;
    }
    if (!isHdsHandle) {
      appEntry.label = bundleResourceInfo.label;
      appEntry.icon = bundleResourceInfo.icon;
      return true;
    }
    if (appEntry.appInfo.bundleType === 0) {
      let hasBorder: boolean = !ThemeManager.getInstance().checkIsOnlineIcon();
      let mask = this.getMask();
      appEntry.icon = this.getCustomHdsIcon(appEntry, bundleResourceInfo.drawableDescriptor,
        HdsDrawableTools.defaultSize, mask, hasBorder) ?? defaultIcon;
      mask.release();
    } else {
      // 元服务图标不接入hds
      appEntry.icon = bundleResourceInfo.drawableDescriptor.getPixelMap();
    }
    appEntry.label = bundleResourceInfo.label;
    if (!appEntry.label) {
      LogUtil.error(`${this.TAG} get label invalid, name: ${appEntry?.name}, appIndex: ${appEntry?.appIndex}`);
      appEntry.label = defaultLabel;
    }

    return true;
  }

  /**
   * 深拷贝pixelMap
   *
   * @param pixelMap 目标pixelMap
   * @returns 拷贝后的pixelMap
   */
  public clonePixelMap(pixelMap: PixelMap): PixelMap {
    const buffer: ArrayBuffer = new ArrayBuffer(pixelMap.getPixelBytesNumber());
    pixelMap.readPixelsToBufferSync(buffer);
    let opts: image.InitializationOptions = {
      pixelFormat: image.PixelMapFormat.BGRA_8888,
      size: pixelMap.getImageInfoSync().size,
      srcPixelFormat: pixelMap.getImageInfoSync().pixelFormat
    }
    let newPixelMap: image.PixelMap = image.createPixelMapSync(buffer, opts);
    return newPixelMap;
  }
}