/*
 * 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 { SCBSceneMode } from '@ohos/windowscene';

import { LogDomain, LogHelper } from '@ohos/basicutils';
import { FloatingDisplayMode } from '@ohos/systemuicommon/Index';
import { AnimationBase, INotificationCardFloatingVm, ASCFWindowMgrAdapter,
  NotificationItemBaseVm } from '@ohos/systemuicommon/newIndex';
import { WantAgentUtil } from '@ohos/systemuicommon/newTsIndex';
import {
  NotificationCardFloatingWantAgentParams
} from '@ohos/systemuicommon/src/main/ets/notification/interface/INotificationCardFloatingVm';
import { NotificationWantAgentInfo, SceneSessionAdapter } from '@ohos/systemuicommon';
import { bundleManager } from '@kit.AbilityKit';

const TAG = 'NotificationCardFloatingVm';
const log = LogHelper.getLogHelper(LogDomain.NC, TAG);

export class NotificationCardFloatingVm extends NotificationItemBaseVm implements INotificationCardFloatingVm {
  private isStartingFloating = false;

  async canOpenFloating(params: NotificationCardFloatingWantAgentParams): Promise<boolean> {
    const agentInfo = params.wantAgentInfo ?? await WantAgentUtil.parseWantAgentInfo(params.wantAgent);
    params.wantAgentInfo = agentInfo;

    if (!await this.isNeedFloating(agentInfo?.bundleName)) {
      log.showInfo(`${this.ntf.key} is not need floating`);
      return false;
    }
    if (await SceneSessionAdapter.getIsMidScene()) {
      log.showInfo('Current window mode is middle scene');
      return false;
    }
    if (!await this.isSupportFloating(agentInfo)) {
      log.showInfo(TAG, `${this.ntf.key} is not supportFloating`);
      return false;
    }

    return true;
  }

  async startFloatingForClick(params: NotificationCardFloatingWantAgentParams): Promise<void> {
    log.showInfo(`startFloatingForClick: ${this.ntf.key}`);
    if (this.isStartingFloating) {
      log.showWarn(`Current is running: ${this.ntf.key}`);
      return;
    }
    this.isStartingFloating = true;
    try {
      this.startFloatingWindow(FloatingDisplayMode.CLICK_WITH_ANIMATION, params);
    } catch (e) {
      log.error(`startFloatingForClick for ${this.ntf.key} error:`, e);
    } finally {
      this.isStartingFloating = false;
    }
  }

  async runCardHideAnimation(event: () => void): Promise<void> {
    const animation = new AnimationBase(AnimationBase.NAMES.FLOATING_LAYER_ANIMATION, true);
    await animation.executeAnimation([
      {
        curve: Curve.Linear,
        duration: 200,
        event,
      }
    ]);
  }

  protected async isNeedFloating(bundleName?: string): Promise<boolean> {
    if (await ASCFWindowMgrAdapter.isWindowModeForMetaService(bundleName)) {
      log.showInfo(TAG, 'app need floating');
      return true;
    }

    return false;
  }

  private async isSupportFloating(wantAgentInfo?: NotificationWantAgentInfo): Promise<boolean> {
    const want = wantAgentInfo?.want;
    log.showInfo(TAG, `checkIsSupportFloating, want:${want?.bundleName}, ${want?.moduleName}, ${want?.abilityName}`);
    if (!this.ntf || !want) {
      return false;
    }

    const bundleName = want.bundleName ?? '';
    const abilityName = want.abilityName ?? '';
    const queryKey: string = bundleName + (want.moduleName ?? '') + abilityName;
    const supportModes =
      await SceneSessionAdapter.getAbilityWindowSupportInfo(queryKey, bundleName, abilityName);
    return supportModes?.indexOf(bundleManager.SupportWindowMode.FLOATING) > -1;
  }

  private async startFloatingWindow(displayMode: FloatingDisplayMode,
    params: NotificationCardFloatingWantAgentParams): Promise<void> {
    log.showInfo(`StartFloatingWindow, displayMode: ${displayMode}`);

    if (!params.wantAgent) {
      log.showWarn(TAG, `No wantAgent for ${this.ntf.key}`);
      return;
    }

    const agentInfo = params.wantAgentInfo ?? await WantAgentUtil.parseWantAgentInfo(params.wantAgent);
    if (!agentInfo?.want) {
      log.showWarn(`No want for ${this.ntf.key}`);
      return;
    }
    await WantAgentUtil.startWantAgent(params.wantAgent, {
      code: 0,
      extraInfos: { floatingDisplayMode: displayMode },
      startOptions: { windowMode: SCBSceneMode.FLOATING },
    });
  }
}