/*
 * 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.
 */

/* instrument ignore file */
import { ObservedData, UiExtensionViewModel } from '@ohos/settings.common/src/main/ets/viewmodel/UiExtensionViewModel';
import { ExitAbnormallyComponent } from '@ohos/settings.common/src/main/ets/viewmodel/ExitAbnormallyComponent';
import { LogUtil } from '@ohos/settings.common/src/main/ets/utils/LogUtil';
import { DeviceUtil } from '@ohos/settings.common/src/main/ets/utils/BaseUtils';
import { PageStartReason } from '@ohos/settings.common/src/main/ets/data/types';
import { Params, PushParam } from '@ohos/settings.common/src/main/ets/core/controller/Controller';
import { ExternalMenuPreloadManager } from '@ohos/settings.common/src/main/ets/externalmenu/ExternalMenuPreloadManager'
import promptAction from '@ohos.promptAction';
import I18n from '@ohos.i18n';
import LightWeightMap from '@ohos.util.LightWeightMap';

const TAG: string = 'AodSettingsPage:';
const BUNDLE_NAME: string = 'com.ohos.sceneboard';
const ABILITY_NAME: string = 'AodSettingsAbility';

enum Intent {
  OPEN_TIME_PICKER_DIALOG = 'open_aod_time_picker_dialog',
  UPDATE_SCHEDULED_SHOW_TIME = 'update_aod_scheduled_show_time',
  SHOW_TOAST = 'show_aod_toast',
  RETURN_PREVIOUS_PAGE = 'return_to_previous_page',
}

interface Action {
  executeAction: (data: Object) => void;
}

@Builder
export function AodSettingsLoader($$: Params): void {
  AodSettings({ params: $$ as Object as PushParam });
}

@Component
struct AodSettings {
  @State observedData: ObservedData = new ObservedData();
  private viewModel: UiExtensionViewModel = new UiExtensionViewModel(this.observedData);
  @Consume('pathInfos') pathStack: NavPathStack;
  private intentMap: LightWeightMap<Intent, Action> = new LightWeightMap();
  private proxy?: UIExtensionProxy;
  private controller?: CustomDialogController;
  @StorageProp('navigationMode') @Watch('onNavigationModeChange') navigationMode: NavigationMode = NavigationMode.Stack;
  private hideBackButton: boolean = false;
  public params: Nullable<PushParam> = undefined;

  recoverController: CustomDialogController = new CustomDialogController({
    builder: ExitAbnormallyComponent(),
  });

  public onNavigationModeChange(): void {
    if (this.params?.startReason === PageStartReason.FROM_SEARCH) {
      this.hideBackButton = this.navigationMode === NavigationMode.Split;
      this.proxy?.send({ 'hideBackButton': this.hideBackButton });
    }
  }

  build() {
    NavDestination() {
      UIExtensionComponent({
        bundleName: BUNDLE_NAME,
        abilityName: ABILITY_NAME,
        parameters: {
          'ability.want.params.uiExtensionType': 'sys/commonUI',
          'hideBackButton': this.hideBackButton,
          'reconnect': this.observedData.reconnect,
        },
      })
        .defaultFocus(true)
        .width('100%')
        .height('100%')
        .onRemoteReady((proxy) => {
          LogUtil.info(`${TAG} UIExtensionComponent onRemoteReady`);
          this.proxy = proxy;
        })
        .onError((error) => {
          LogUtil.info(`${TAG} UIExtensionComponent onError code: ${error?.code} message: ${error?.message}`);
          this.viewModel.refreshing(error, this.recoverController, BUNDLE_NAME, ABILITY_NAME);
        })
        .onTerminated(()=>{})
        .onReceive((data) => {
          LogUtil.info(`${TAG} UIExtensionComponent onReceive`);
          this.intentMap.get(data['intent'] as Intent)?.executeAction(data['data']);
        });
    }
    .hideTitleBar(true)
    .backgroundColor($r('sys.color.ohos_id_color_sub_background'))
    .width('100%')
    .height('100%')
    .onShown(() => {
      LogUtil.info(`${TAG} NavDestination onShown`);
    })
    .onHidden(() => {
      LogUtil.info(`${TAG} NavDestination onHidden`);
    });
  }

  aboutToAppear(): void {
    LogUtil.info(`${TAG} aboutToAppear`);
    this.viewModel.listening(this.recoverController);
    this.intentMap.set(Intent.SHOW_TOAST, { executeAction: this.showToast });
    this.intentMap.set(Intent.OPEN_TIME_PICKER_DIALOG, { executeAction: this.openTimePickerDialog });
    this.intentMap.set(Intent.RETURN_PREVIOUS_PAGE, { executeAction: this.returnPreviousPage });
    if (this.params?.startReason === PageStartReason.FROM_SEARCH && this.navigationMode === NavigationMode.Split) {
      // 设置中搜索跳转时,若设置分栏,则隐藏返回按钮
      this.hideBackButton = true;
    }
  }

  aboutToDisappear(): void {
    LogUtil.info(`${TAG} aboutToDisappear`);
    this.viewModel.destroyListening();
    try {
      ExternalMenuPreloadManager.getInstance().preloadUIExtensionAbility(ABILITY_NAME, getContext());
    } catch (err) {
      LogUtil.showInfo(TAG, `preload AodSettingsAbility failed. err: ${err?.code} ${err?.message}`);
    }
  }

  private returnPreviousPage: (data: Object) => void = () => {
    LogUtil.info(`${TAG} Return To Previous Page`);
    this.pathStack.pop();
  }

  private showToast: (data: Object) => void = (data) => {
    LogUtil.info(`${TAG} Show AOD Toast`);
    promptAction?.showToast({ message: data.toString() });
  }

  private openTimePickerDialog: (data: Object) => void = (data) => {
    LogUtil.info(`${TAG} Open AOD Time Picker Dialog`);
    let initialData = data as AodDialogData;
    let finalData = new AodDialogData();
    finalData.type = initialData.type;
    let finalTime = new Date(initialData.time ?? 0);

    this.controller = new CustomDialogController({
      builder: AodTimePickerDialog({
        data: data,
        handleCancelClick: () => {
          this.controller?.close();
          this.controller = undefined;
        },
        handleConfirmClick: () => {
          this.controller?.close();
          this.controller = undefined;
          if (finalTime.toString() !== initialData.time) {
            finalData.time = finalTime.toString();
            this.proxy?.send({ 'intent': Intent.UPDATE_SCHEDULED_SHOW_TIME, 'data': finalData });
          }
        },
        handleDateChange: (value: TimePickerResult) => {
          finalTime.setHours(value.hour ?? 0);
          finalTime.setMinutes(value.minute ?? 0);
        }
      }),
      gridCount: DeviceUtil.isDevicePhone() ? 4 : undefined,
      alignment: DeviceUtil.isDevicePhone() ? DialogAlignment.Bottom : undefined,
    });
    this.controller?.open();
  }
}

@CustomDialog
struct AodTimePickerDialog {
  controller?: CustomDialogController;
  private data: AodDialogData = new AodDialogData();
  private handleConfirmClick?: (event: ClickEvent) => void;
  private handleCancelClick?: (event: ClickEvent) => void;
  private handleDateChange?: (value: TimePickerResult) => void;

  build() {
    Column() {
      Text(this.data.titleText)
        .fontWeight(FontWeight.Medium)
        .fontSize($r('sys.float.ohos_id_text_size_dialog_tittle'))// 20.0fp
        .fontColor($r('sys.color.ohos_id_color_text_primary'));

      TimePicker({ selected: new Date(this.data.time ?? 0) })
        .useMilitaryTime(I18n.System.is24HourClock())
        .backgroundColor(Color.Transparent)
        .width('100%')
        .margin({
          top: $r('sys.float.ohos_id_default_padding_top'), // 24.0vp
          bottom: $r('sys.float.ohos_id_default_padding_top') // 24.0vp
        })
        .onChange(this.handleDateChange);

      Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {
        Button(this.data.buttonCancelText ?? '')
          .fontWeight(FontWeight.Medium)
          .fontSize($r('sys.float.ohos_id_text_size_button1'))// 16.0fp
          .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
          .backgroundColor(Color.Transparent)
          .width('100%')
          .onClick(this.handleCancelClick);

        Divider()
          .vertical(true)
          .strokeWidth(1)
          .margin({
            left: $r('sys.float.ohos_id_elements_margin_horizontal_m'), // 8.0vp
            right: $r('sys.float.ohos_id_elements_margin_horizontal_m') // 8.0vp
          })
          .height(24);

        Button(this.data.buttonConfirmText ?? '')
          .fontWeight(FontWeight.Medium)
          .fontSize($r('sys.float.ohos_id_text_size_button1'))// 16.0fp
          .fontColor($r('sys.color.ohos_id_color_text_primary_activated'))
          .backgroundColor(Color.Transparent)
          .width('100%')
          .onClick(this.handleConfirmClick);
      }
      .width('100%');
    }
    .padding($r('sys.float.ohos_id_max_padding_start')) // 24vp
    .width('100%');
  }
}

class AodDialogData {
  public type?: string;
  public time?: string;
  public titleText?: string;
  public buttonConfirmText?: string;
  public buttonCancelText?: string;
}