/*
 * 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 nfcController from '@ohos.nfc.controller';
import { SettingsBaseMenu } from '@ohos/settings.common/src/main/ets/core/model/menu/SettingsMenu';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { Controller } from '@ohos/settings.common/src/main/ets/core/controller/Controller';
import { HiSysEventUtil } from '@ohos/settings.common/src/main/ets/systemEvent/HiSysEventUtil';
import { HiSysNfcEventGroup } from '@ohos/settings.common/src/main/ets/systemEvent/BehaviorEventConsts';
import emitter from '@ohos.events.emitter';
import { EVENT_ID_NFC_SWITCH_CHANGE } from '@ohos/settings.common/src/main/ets/event/types';
import { SwitchMenuController } from '@ohos/settings.common/src/main/ets/core/controller/MenuController';
import { NFCStateChangeListener, NFCUtil } from '../NFCUtil';

const CHANGE_NFC_SWITCH: string = 'change_nfc_switch';
const TAG: string = 'NFCServiceController : ';
const INACTIVE: number = nfcController?.NfcState?.STATE_OFF;
const ACTIVE: number = nfcController?.NfcState?.STATE_ON;
const ACTIVATING: number = nfcController?.NfcState?.STATE_TURNING_ON;
const DEACTIVATING: number = nfcController?.NfcState?.STATE_TURNING_OFF;
const SWITCH_DELAY: number = 500;
const SWITCH_MAX_TIME: number = 5000; // 5s

export function getNfcStatusForReport():boolean {
  return nfcController.isNfcOpen();
}

export class NFCServiceController extends SwitchMenuController implements NFCStateChangeListener {
  static CreateNFCServiceController(menu: SettingsBaseMenu): Controller {
    return new NFCServiceController(menu);
  }

  // 用于表示目标状态 1: STATE_OFF, 2: STATE_TURNING_ON, 3: STATE_ON, 4: STATE_TURNING_OFF
  public targetState: number | null = null;
  public currentState: number | null = null; // 用于获取当前开关状态
  public taskTimerId: number | null = null; // taskTimerId 用于设置任务的完成时间
  public switchTimerId: number | null = null; // switchTimerId 开关能容忍的切换完成时间

  getListenerName(): string {
    return this.menu.key ?? ' ';
  }

  aboutToAppear(): void {
    LogUtil.info(`${TAG} aboutToAppear`);
    super.aboutToAppear();
  }

  onNFCStateChange(stateChanged: nfcController.NfcState): void {
    LogUtil.info(`${TAG} listener find nfc service isChanged: ${stateChanged}`);
    this.currentState = stateChanged;

    if (stateChanged === nfcController?.NfcState?.STATE_OFF || stateChanged === nfcController?.NfcState?.STATE_ON) {
      this.emitNfcStatus();
    }

    if (this.taskTimerId !== null) { // taskTimerId存在,则说明此时生成任务
      // 用户点击,切换任务中
      this.updateToTargetState(SWITCH_DELAY);
    } else {
      // 外部切换事件接收
      if (this.currentState !== ACTIVE && this.currentState !== INACTIVE) {
        // 中间态,切换中
        return;
      }
      this.updateTargetStateValue(this.currentState);
      this.setChecked(this.currentState === ACTIVE ? true : false);
      this.refreshUi();
    }
  }

  // aboutToAppear会调用,用于更新按钮状态
  protected updateCheckedState(): boolean {
    let isChecked: boolean = nfcController.isNfcOpen();
    this.currentState = isChecked ? ACTIVE : INACTIVE;
    LogUtil.info(`${TAG} updateCheckedState ${isChecked}`);
    this.updateTargetStateValue(this.currentState);
    return isChecked;
  }

  protected handleCheckedChange(isChecked: boolean): boolean {
    if (isChecked === this.getChecked()) {
      LogUtil.info(`${this.tag} handleCheckedChange isChecked not change : ${isChecked}`);
      return false;
    }

    HiSysEventUtil.reportDefaultBehaviorEventByUE(HiSysNfcEventGroup.CLICK_NFC_BUTTON, isChecked ? 'true' : 'false');
    LogUtil.info(`${TAG} enter handleCheckedChange...`);
    this.updateTargetStateValue(isChecked ? ACTIVE : INACTIVE);
    return this.startTask();
  }

  private updateTargetStateValue(state: number): void {
    LogUtil.info(`${TAG} updateTargetStateValue ${state}`);
    this.targetState = state;
  }

  updateToTargetState(delay: number = 0): boolean {
    if (this.taskTimerId === null) { // 重复点击时间,使得之前的任务被取消执行
      LogUtil.error(`${TAG} taskTimerId null`);
      return true;
    }
    if (this.currentState !== ACTIVE && this.currentState !== INACTIVE) {
      // 中间态,切换中, 等待切换完成
      LogUtil.info(`${TAG} in task, currentState ${this.currentState}`);
      return true;
    }
    if (this.currentState === this.targetState) {
      // 非中间态,且已经目标态,任务结束
      LogUtil.info(`${TAG} task finish, currentState ${this.currentState}`);
      if (this.currentState === ACTIVE) {
        HiSysEventUtil.reportSwitchEvent(CHANGE_NFC_SWITCH, 'on');
      } else if (this.currentState === INACTIVE) {
        HiSysEventUtil.reportSwitchEvent(CHANGE_NFC_SWITCH, 'off');
      }
      this.stopTask();
      return true;
    }

    // 非中间态,且不是目标态,开始切换到目标态
    if (this.switchTimerId !== null) {
      clearTimeout(this.switchTimerId);
      this.switchTimerId = null;
    }

    this.switchTimerId = setTimeout(() => {
      this.switchNFC();
      this.switchTimerId = null;
    }, delay);

    return true;
  }

  private switchNFC(): void {
    if (this.currentState !== ACTIVE && this.currentState !== INACTIVE) {
      // 中间态,不切换
      LogUtil.info(`${TAG} switchBluetooth, in task, currentState ${this.currentState}`);
      return;
    }

    LogUtil.info(`${TAG} switchNFC, targetState : ${this.targetState}`);
    let result = (this.targetState === ACTIVE) ? this.enableNfc() : this.disableNfc();
    if (result) {
      this.currentState = this.targetState === ACTIVE ? ACTIVATING : DEACTIVATING;
      LogUtil.info(`${TAG} enable or disable success, currentState ${this.currentState}`);
    } else {
      // 切换失败
      LogUtil.error(`${TAG} enable or disable failed`);
      this.stopTask();
      this.updateStatus();
    }
  }

  // 用于规避重复点击事件
  private startTask(): boolean {
    this.stopTask();
    LogUtil.info(`${TAG} task start, currentState ${this.currentState}`);
    this.taskTimerId = setTimeout(() => {
      this.taskTimerId = null; // 开始新任务时,先清空现有的 taskTimerId
      LogUtil.info(`${TAG} switch task timeout`);
      this.updateStatus();
    }, SWITCH_MAX_TIME);

    return this.updateToTargetState();
  }

  private stopTask(): void {
    if (this.taskTimerId !== null) { // 将现有的taskTimerId清空
      clearTimeout(this.taskTimerId);
      this.taskTimerId = null;
    }

    if (this.switchTimerId !== null) { // 将现有的switchTimerId清空
      clearTimeout(this.switchTimerId);
      this.switchTimerId = null;
    }
  }

  private enableNfc(): boolean {
    if (nfcController?.isNfcOpen() === true) {
      LogUtil.info(`${TAG} nfc is already active`);
      return true;
    }
    let isSuccess: boolean = nfcController?.openNfc();
    LogUtil.info(`${TAG} enable nfc result is : ${isSuccess}`);
    return isSuccess;
  }

  private disableNfc(): boolean | undefined {
    if (nfcController?.isNfcOpen() !== true) {
      LogUtil.info(`${TAG} nfc is already inactive`);
      return;
    }
    let isSuccess: boolean = nfcController?.closeNfc();
    LogUtil.info(`${TAG} disable nfc result is : ${isSuccess}`);
    return isSuccess;
  }

  private emitNfcStatus(): void {
    let state: boolean = false;
    try {
      state = nfcController?.isNfcOpen();
      LogUtil.info(`${TAG} update nfc service state, state: ${state}`);
    } catch (err) {
      LogUtil.error(`${TAG} check nfcStatus api failed`);
    }

    emitter.emit({
      eventId: EVENT_ID_NFC_SWITCH_CHANGE,
      priority: emitter.EventPriority.IMMEDIATE,
    }, { data: { 'defaultAppState': state } });
    LogUtil.info(`${TAG} emitter.emit`);
  }

  protected registerDataChange(): void {
    LogUtil.info(`${TAG} registerDataChange`);
    NFCUtil.getInstance().registerStateChangeListener(this);
  }

  protected unRegisterDataChange(): void {
    LogUtil.info(`${TAG} unRegisterDataChange`);
    NFCUtil.getInstance().unRegisterStateChangeListener(this);
  }
}