/*
 * Copyright (c) Huawei Device 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 { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { EvtBus } from '@ohos/frameworkwrapper';
import { CommonUtils, LogDomain, Logger } from '@ohos/basicutils';
import { GestureState, SysDialogParamsKey, SysDialogZOrder, FocusState } from '../common/Constants';
import { DialogDataEvent, IParameters, ISystemDialogData } from '../common/DialogDataEvent';
import { SystemDialogEventUtil, SystemDialogState } from '../common/SysDialogEventUtil';
import { SCBScreenSessionManager } from '@ohos/windowscene';

const TAG = 'Dialog-ServiceExtensionAbility2';
const GT_KEY = TAG + 'SystemDialogController';
const log: Logger = Logger.getLogHelper(LogDomain.SYS_UI);
const DATA_SUCCESS_CODE = 0;
const DATA_ERROR_CODE = 1;

class SystemDialogController {
  private count: number = 0;
  private data: Map<string, ISystemDialogData> = new Map();
  private defaultList: Array<ISystemDialogData> = [];
  private upperList: Array<ISystemDialogData> = [];
  private context: common.ServiceExtensionContext | null = null;
  private sysDialogStatus: boolean = false;
  // 多屏下弹窗与screenId的映射
  private statusMapScreen: Map<number, boolean> = new Map([
    [0, false],
  ]);
  private static _instance: SystemDialogController | undefined

  setStatusByScreenId(screenId: number, status: boolean): void {
    log.showInfo(TAG, `setStatusByScreenId ${screenId} ${status}`);
    this.statusMapScreen.set(screenId, status);
  }

  getStatusByScreenId(screenId: number): boolean {
    const status = this.statusMapScreen.get(screenId);
    log.showInfo(TAG, `getStatusByScreenId ${screenId} ${status}`);
    return status || false;
  }

  setSysDialogStatus(status: boolean): void {
    log.showInfo(TAG, `setSysDialogStatus ${status}`);
    this.sysDialogStatus = status;
  }

  getSysDialogStatus(): boolean {
    return this.sysDialogStatus;
  }
  /**
   * 弹框数据刷新事件
   */
  private dataEvent: DialogDataEvent = new DialogDataEvent();

  /**
   * 数据删除,更新UI
   */
  private setDataEvent(sysDialogZOrder: SysDialogZOrder, list: Array<ISystemDialogData>,
    item: ISystemDialogData): void {
    log.showInfo(TAG, `setDataEvent start`);
    this.dataEvent.dialogZOrder = sysDialogZOrder;
    this.dataEvent.dataList = [...list];
    this.dataEvent.defaultList = [...this.defaultList];
    this.dataEvent.upperList = [...this.upperList];
    this.dataEvent.item = item;
    EvtBus.post(DialogDataEvent, this.dataEvent);
    log.showInfo(TAG, `setDataEvent end`);
  }

  static getInstance(): SystemDialogController {
    if (SystemDialogController._instance === null || SystemDialogController._instance === undefined) {
      SystemDialogController._instance = new SystemDialogController();
    }
    return SystemDialogController._instance;
  }

  setContext(context: common.ServiceExtensionContext): void {
    this.context = context;
    log.showInfo(TAG, 'setContext end');
  }

  getContext(): common.ServiceExtensionContext {
    return this.context as common.ServiceExtensionContext;
  }

  getList(zOrder: SysDialogZOrder): Array<ISystemDialogData> {
    log.showInfo(TAG, `getList start ${zOrder}`);
    if (zOrder === SysDialogZOrder.DEFAULT) {
      return this.defaultList;
    }

    return this.upperList;
  }

  isAllListEmpty(): boolean {
    const empty = this.defaultList.length === 0 && this.upperList.length === 0;
    log.showInfo(TAG, `isAllListEmpty ${empty}`);
    if (this.defaultList.length) {
      const list = this.defaultList?.map(item => {
        return `${item?.id} ${item?.want?.abilityName}`;
      });
      log.showWarn(TAG, `isAllListEmpty ${empty} ${list?.toString()}`);
    }
    return empty;
  }

  getData(): Map<string, ISystemDialogData> {
    return this.data;
  }

  addDataByKey(key: string, v: ISystemDialogData): void {
    log.showInfo(TAG, `${key} addDataByKey start`);
    const sysDialogZOrder = v.sysDialogZOrder;
    const needPush = sysDialogZOrder === SysDialogZOrder.DEFAULT || sysDialogZOrder === SysDialogZOrder.UPPER;
    const oldSysDialogZOrder = this.data.get(key)?.sysDialogZOrder;

    this.data.set(key, v);

    if (!needPush) {
      log.showWarn(TAG, `${key} addDataByKey no-push`);
      return;
    }

    if (typeof oldSysDialogZOrder === 'number') {
      log.showInfo(TAG, `${key} addDataByKey findAndRemoveFromLists`);
      this.findAndRemoveFromLists(key, oldSysDialogZOrder);
    }

    log.showInfo(TAG, `${key} addDataByKey before default:${this.defaultList.length} upper:${this.upperList.length}`);

    const list = this.getList(sysDialogZOrder);
    list.push(v);

    // 数据刷新,更新UI
    this.setDataEvent(sysDialogZOrder, list, v);

    log.showInfo(TAG, `${key} addDataByKey end ${sysDialogZOrder} len:${this.defaultList.length} ${this.upperList.length}`);
    SystemDialogEventUtil.reportSystemDialogEvent(SystemDialogEventUtil.EVENT_NAME,
      v, SystemDialogState.OPEN);
    // 弹窗获焦模式打点,后续打点需要整改
    const focusState = v.want?.parameters?.focusState;
    if (focusState === FocusState.DISABLE || focusState === FocusState.ENABLE) {
      SystemDialogEventUtil.reportSystemDialogEvent(SystemDialogEventUtil.EVENT_NAME, v,
        focusState === FocusState.DISABLE ? SystemDialogState.DISABLE_FOCUS : SystemDialogState.ENABLE_FOCUS);
    }
  }

  removeDataByKey(key: string): number {
    log.showInfo(TAG, `${key} removeDataByKey start`);

    const item = this.data.get(key);
    if (!item) {
      log.showError(TAG, `${key} removeDataByKey: data is null`);
      return DATA_ERROR_CODE;
    }
    const sysDialogZOrder = item.sysDialogZOrder!;
    this.findAndRemoveFromLists(key, sysDialogZOrder);
    this.data.delete(key);

    log.showInfo(TAG, `${key} removeDataByKey end`);
    SystemDialogEventUtil.reportSystemDialogEvent(SystemDialogEventUtil.EVENT_NAME,
      item, SystemDialogState.CLOSE);
    return DATA_SUCCESS_CODE;
  }

  findAndRemoveFromLists(key: string, sysDialogZOrder: SysDialogZOrder): void {
    const list = this.getList(sysDialogZOrder);
    log.showInfo(TAG, `${key} findAndRemoveFromLists start ${sysDialogZOrder} length ${list.length}`);

    this.closeByConnectId(key, sysDialogZOrder, false);
  }

  /**
   * 返回所有的连接id
   */
  getListConnectId(list: ISystemDialogData[]): string {
    return list?.map(o => o?.connectId).toString();
  }

  /**
   * 根据connectId关闭弹窗内容
   * @param connectId 连接id
   * @param sysDialogZOrder 弹窗层级
   * @param needClear 是否需要清除
   */
  closeByConnectId(
    connectId: string,
    sysDialogZOrder: SysDialogZOrder,
    needClear: boolean = true,
    abilityName: string = ''
  ): void {
    if (connectId.length < 0) {
      log.showError(TAG, `${connectId} closeByConnectId end by index<0`);
      return;
    }
    const list = this.getList(sysDialogZOrder);
    log.showInfo(TAG, `${connectId} closeByConnectId before ${this.getListConnectId(list)}`);

    if (list.length === 0) {
      log.showError(TAG, `${connectId} closeByConnectId end by list.length=0`);
      return;
    }
    const index = list.findIndex(item => {
      if (abilityName) {
        return item.connectId === connectId && item.want.abilityName === abilityName;
      } else {
        return item.connectId === connectId;
      }
    });
    log.showInfo(TAG, `${connectId} closeByConnectId index ${index} ${abilityName}`);
    if (index === -1) {
      return;
    }
    const item = (list.splice(index, 1))[0];
    log.showInfo(TAG, `${connectId} closeByConnectId after ${this.getListConnectId(list)}`);
    this.unlockRotationForPowerOff(item);

    // 数据删除,更新UI
    this.setDataEvent(sysDialogZOrder, list, item);

    if (needClear) {
      this.data.delete(item.id);
    }

    log.showInfo(TAG, `${connectId} closeByConnectId end list length ${list.length}`);
    SystemDialogEventUtil.reportSystemDialogEvent(SystemDialogEventUtil.EVENT_NAME,
      item, SystemDialogState.CLOSE);
  }

  unlockRotationForPowerOff(item: ISystemDialogData): void {
    const abilityName = item?.want?.abilityName;
    if (abilityName === 'PoweroffAbility') {
      const screenSession = SCBScreenSessionManager.getInstance()?.getMainScreenSession();
      if (CommonUtils.isInvalid(screenSession)) {
        log.showInfo(TAG, `unlock power off page rotation failed`);
        return;
      }
      log.showInfo(TAG, `unlock powe roff start`);
      screenSession?.setEnableRotate(true, 'poweroff');
      log.showInfo(TAG, `unlock power off end`);
      screenSession?.rotationChangeEntry(screenSession.sensorScreenProperty.rotation, 'unlock power off page rotation');
      log.showInfo(TAG, 'unlock power off page rotation');
    }
  }

  /**
   * 根据指定的key过滤
   * @param list 应用列表
   * @param key 过滤的key
   * @param target 目标值
   * @returns []
   */
  filterListByKey(list: ISystemDialogData[], key: string, target: number): ISystemDialogData[] {
    const filterList = list.filter((item: ISystemDialogData) => {
      const want = item.want;
      const targetKey = want?.parameters ? Reflect.get(want?.parameters as IParameters, key) as number : undefined
      if (targetKey === target) {
        log.showInfo(TAG, `filter ${key} bundleName:${want?.bundleName} abilityName:${want?.abilityName}`);
        return true;
      }
      return false;
    });
    return filterList;
  }

  closeAll(): void {
    log.showInfo(TAG, 'closeAll start');

    const clearList = (list: ISystemDialogData[], sysDialogZOrder: SysDialogZOrder): void => {
      for (let index = list.length - 1; index >= 0; index--) {
        this.closeByConnectId(list[index]?.connectId, sysDialogZOrder);
      }
    };

    clearList(this.defaultList, SysDialogZOrder.DEFAULT);
    clearList(this.upperList, SysDialogZOrder.UPPER);

    log.showWarn(TAG, `closeAll end ${this.defaultList.length} ${this.upperList.length}`);
  }

  requestDestroy(): void {
    if (this.isAllListEmpty()) {
      this.destroy();
    }
  }

  // 清理所有数据
  clearAll(): void {
    try {
      // 检查多弹窗中是否存在霸屏窗口
      const allList: ISystemDialogData[] = [...this.defaultList, ...this.upperList];
      const data = this.filterListByKey(allList, SysDialogParamsKey.disableUpGesture, GestureState.ENABLE);
      const isExistDisableUpGestureDialog = data?.length > 0;
      log.showInfo(TAG, `clearAll isExistDisableUpGestureDialog ${isExistDisableUpGestureDialog}`);
      if (!isExistDisableUpGestureDialog) {
        this.closeAll();
        this.destroy();
        log.showInfo(TAG, `clearAll end`);
      } else {
        const disableList = data.map(item => `${item.want.bundleName}:${item.want.abilityName}`).toString();
        log.showWarn(TAG, `clearAll stop ${disableList}`);
      }
    } catch (error) {
      log.showError(TAG, `clearAll error ${error}`);
    }
  }

  destroy(): void {
    log.showInfo(TAG, 'clear start');
    this.data?.clear();
    this.context?.terminateSelf((error: BusinessError) => {
      if (error.code) {
        log.showError(TAG, `terminateSelf failed, error.code: ${error.code}, error.message: ${error.message}`);
        return;
      }
      log.showWarn(TAG, 'terminateSelf in file:Controller>destroy');
    });
    this.context = null;
    log.showInfo(TAG, 'clear end');
  }
}

export default SystemDialogController;