/*
 * 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 intl from '@ohos.intl';
import { AccountUtil } from '@ohos/settings.common/src/main/ets/utils/AccountUtil';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { NavEntryKey, AppGroupType } from '@ohos/settings.common/src/main/ets/utils/Consts';
import { TabIndexConstants } from '@ohos/settings.common/src/main/ets/constant/TabIndexConstants';
import { HiSysEventUtil } from '@ohos/settings.common/src/main/ets/systemEvent/HiSysEventUtil';
import { PageRouter } from '@ohos/settings.common/src/main/ets/framework/common/PageRouter';
import { OrderedDataSource } from '@ohos/settings.common/src/main/ets/framework/model/OrderedDataSource';
import {
  CompCtrlParam,
  ComponentControl,
  SettingBaseModel
} from '@ohos/settings.common/src/main/ets/framework/model/SettingBaseModel';
import {
  ComparableSettingItemModel,
  ItemDetailType,
  ItemType,
  SettingIconStyle,
  SettingIconType,
  SettingItemLayout,
  SettingItemModel
} from '@ohos/settings.common/src/main/ets/framework/model/SettingItemModel';
import { PageStartModeManager } from '@ohos/settings.common/src/main/ets/window/PageStartModeManager';
import { EventBus } from '@ohos/settings.common/src/main/ets/framework/common/EventBus';
import { PageStartReason } from '@ohos/settings.common/src/main/ets/data/types';
import { AppListLoader } from '../AppListLoader';
import { AppEntry, AppType } from '../AppModel';
import { AppUtils } from '../AppUtils';
import { AppCloneBadgeComponent } from '../components/AppCloneBadgeComponent';
import { AppEntryUtil } from '../util/AppEntryUtil';
import { ThemeManager } from '../util/ThemeManager';

const TAG: string = 'BundleListController';

@Builder
function appCloneBadgeBuilder(param: object): void {
  AppCloneBadgeComponent({
    appCloneBadgeParam: param as SettingItemModel,
    iconSize: 48,
    bundleName: ((param as SettingItemModel)?.extra as AppEntry)?.name
  })
}

export class BundleListController implements ComponentControl {
  private dataSource?: OrderedDataSource;
  private id?: string;
  private menuCache: ComparableSettingItemModel[] = [];
  private index: number = 0;
  private appListLoadEventCb = (data: Object) => {
    let eventData: string = (data === undefined || data === null) ? '' : data.toString();
    // 如果传回来一个空的字符串,则表示所有BundleListController示例都响应,否则只更新指定的列表
    if (eventData.length !== 0 && data !== this.id) {
      return;
    }
    this.onAppListChanged();
  };
  private appListAddEventCb = (data: object) => {
    LogUtil.info(`${TAG} app list add`);
    let appEntry = data as AppEntry;
    if (appEntry) {
      this.onAppListAdd(appEntry);
    }
  };
  private appListRemoveCb = (data: object, appIndex: number) => {
    LogUtil.info(`${TAG} app list remove`);
    let bundleName = (data as String).toString();
    if (bundleName) {
      this.onAppListRemove(bundleName, appIndex);
    }
  };

  private appListRemoveAllCb = () => {
    this.dataSource?.removeAll();
  }

  async init(compParam: CompCtrlParam): Promise<void> {
    LogUtil.info(`${TAG} init`);
    this.id = compParam.component.id;
    this.dataSource = compParam.dataSource as OrderedDataSource;
    EventBus.getInstance().on('EVENT_ID_APP_LIST_LOADER', this.appListLoadEventCb);
    EventBus.getInstance().on('EVENT_ID_APP_LIST_ADD', this.appListAddEventCb);
    EventBus.getInstance().on('EVENT_ID_APP_LIST_REMOVE', this.appListRemoveCb);
    EventBus.getInstance().on('EVENT_ID_APP_LIST_REMOVE_ALL', this.appListRemoveAllCb);
    AppStorage.setOrCreate('isCurrentPrivate', await AccountUtil.isCurrentPrivate());
  }

  destroy(): void {
    LogUtil.info(`${TAG} onDestroy`);
    EventBus.getInstance().detach('EVENT_ID_APP_LIST_LOADER', this.appListLoadEventCb);
    EventBus.getInstance().detach('EVENT_ID_APP_LIST_ADD', this.appListAddEventCb);
    EventBus.getInstance().detach('EVENT_ID_APP_LIST_REMOVE', this.appListRemoveCb);
    EventBus.getInstance().detach('EVENT_ID_APP_LIST_REMOVE_ALL', this.appListRemoveAllCb);
  }

  private onAppListChanged(): void {
    let filterAppList: AppEntry[] = AppListLoader.getInstance().getAppListCache(this.id);
    if (filterAppList.length > 0) {
      this.addMenu(filterAppList);
    } else {
      LogUtil.error(`${TAG} getAppList failed`);
    }
    this.onServiceCountUpdate();
    LogUtil.info(`${TAG} onAppListChanged , filterAppList: ${filterAppList.length}`);
  }

  private addMenu(appList: AppEntry[]): void {
    LogUtil.info(`${TAG} appList.length:${appList.length}, this.dataSource:${this.dataSource?.length}`)
    this.menuCache = [];
    appList.forEach((item, index) => {
      this.menuCache.push({
        id: AppUtils.getAppKey(item.name, item.appIndex),
        type: ItemType.ITEM_TYPE_STANDARD,
        subId: ThemeManager.getInstance().getCurrentThemeId(),
        icon: {
          icon: item.icon as ResourceStr,
          iconType: SettingIconType.ICON_TYPE_APPICON,
          // style: this.getIconStyle(),
          builder: AppEntryUtil.isAppCloneBadge(item) || (this.id === AppGroupType.CONTAINER)
            ? wrapBuilder(appCloneBadgeBuilder) : undefined
        },
        title: { content: item?.label ?? '' },
        compare: (dst: ComparableSettingItemModel) => {
          return 0;
        },
        desc: { content: '' },
        tabIndex: !index ? TabIndexConstants.TAB_INDEX_LEVEL2_PAGE : TabIndexConstants.TAB_INDEX_DEFAULT,
        detail: {
          type: ItemDetailType.DETAIL_TYPE_CUSTOM,
          icon: $r('sys.symbol.chevron_right'),
          isSymbolIcon: true,
          onItemClick: (component: SettingBaseModel) => {
            this.onHandlerItemClick(component);
          },
        },
        layout: this.getLayout(),
        extra: item
      })
    })
    this.dataSource?.splice(0, this.dataSource.length);
    this.refreshAllData();
  }

  private refreshAllData(): void {
    if (!this.dataSource) {
      return;
    }

    this.dataSource.push(...this.menuCache);
    this.dataSource.notifyDataReload();
  }

  protected getLayout(): SettingItemLayout | undefined {
    return undefined;
  }

  protected getIconStyle(): SettingIconStyle {
    // 接入了HDS之后,图标不需要主动做描边处理
    let style: SettingIconStyle = {
      border: { width: '0px', color: '#00000000', radius: 0 },
      borderRadius: 0,
      width: 48,
      height: 48,
      mirrored: false,
      draggable: false
    };
    return style;
  }

  private onHandlerItemClick(e: SettingBaseModel): void {
    LogUtil.info(`${TAG} AppEntryController onMenuClick ${e.id}`);
    const APP_INFO_ENTRY: string = 'app_info_entry';
    HiSysEventUtil.reportEntryEvent(APP_INFO_ENTRY, e.id);
    let checkedApp: ComparableSettingItemModel =
      this.dataSource?.find(i => i.id === e.id) as ComparableSettingItemModel;
    AppStorage.setOrCreate('currentAppName', checkedApp?.title?.content);
    PageStartModeManager.getInstance().setStartReason(PageStartReason.DEFAULT);
    PageRouter.push(NavEntryKey.APPLICATION_INFO_ENTRY, AppUtils.parsePushParamFromAppKey(e.id));
  }

  private onAppListAdd(appEntry: AppEntry): void {
    let flag: boolean = false;
    switch (this.id) {
      case AppGroupType.SYSTEM:
        flag = AppListLoader.getInstance().getAppType(appEntry) === 'systemApp';
        break;
      case AppGroupType.UN_SYSTEM:
        flag = AppListLoader.getInstance().getAppType(appEntry) === 'unSystemApp';
        break;
      case AppGroupType.SERVICE:
        flag = AppListLoader.getInstance().getAppType(appEntry) === 'meetaApp';
        break;
      case AppGroupType.CONTAINER:
        flag = AppListLoader.getInstance().getAppType(appEntry) === 'containerApp';
        break;
      default:
        break;
    }
    if (!flag) {
      return;
    }
    this.pushDataToDataSource(appEntry);
    this.onServiceCountUpdate();
  }

  private pushDataToDataSource(appEntry: AppEntry): void {
    let item: ComparableSettingItemModel = {
      id: AppUtils.getAppKey(appEntry?.name, appEntry?.appIndex),
      type: ItemType.ITEM_TYPE_STANDARD,
      icon: {
        icon: appEntry?.icon as ResourceStr,
        iconType: SettingIconType.ICON_TYPE_APPICON,
        style: this.getIconStyle(),
        builder: (this.id === AppGroupType.CONTAINER) ? wrapBuilder(appCloneBadgeBuilder) : undefined
      },
      title: { content: appEntry?.label ?? '' },
      compare: (dst: ComparableSettingItemModel) => {
        let collator = new intl.Collator();
        return collator.compare((dst.title?.content ?? '').toString(), (appEntry?.label ?? '').toString());
      },
      desc: { content: '' },
      detail: {
        type: ItemDetailType.DETAIL_TYPE_CUSTOM,
        icon: $r('sys.symbol.chevron_right'),
        isSymbolIcon: true,
        onItemClick: (component: SettingBaseModel) => {
          this.onHandlerItemClick(component);
        },
      },
      extra: appEntry
    };
    this.dataSource?.pushData(item);
  }

  private onAppListRemove(bundleName: string, appIndex: number): void {
    let index = this.dataSource?.findIndex(item => item.id === AppUtils.getAppKey(bundleName, appIndex)) ?? -1;
    if (index !== -1) {
      LogUtil.info(`${TAG} remove app, name: ${bundleName}, appIndex: ${appIndex}`);
      this.dataSource?.removeDataByIndex(index);
      this.onServiceCountUpdate();
    }
  }

  private onServiceCountUpdate(): void {
    if (this.id === AppGroupType.SERVICE) {
      let curServiceCount = AppListLoader.getInstance().getAppListCache(AppType.SERVICE_APP).filter((menu) => {
        return menu.appInfo?.bundleType === 1;
      }).length;
      LogUtil.info(`${TAG} current service count: ${curServiceCount}`);
      EventBus.getInstance().emit('EVENT_ID_SERVICE_EMPTY', curServiceCount === 0);
    }
  }
}