/*
 * Copyright (c) 2026-2026 Huawei Device Co., Ltd.
 * 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 { BusinessError } from '@ohos.base';
import hilog from '@ohos.hilog';
import { KeyCode } from '@ohos.multimodalInput.keyCode';
import resourceManager from '@ohos.resourceManager';
import { Theme } from '@ohos.arkui.theme';
import { LengthMetrics } from '@ohos.arkui.node';
import common from '@ohos.app.ability.common';
import window from '@ohos.window';
import { Context } from '@ohos.arkui.UIContext';
import { SymbolGlyphModifier } from '@kit.ArkUI';
import { EnvironmentCallback } from '@kit.AbilityKit';
import emitter from '@ohos.events.emitter';
import { promptAction } from '@kit.ArkUI';

export enum EditableLeftIconTypeV2 {
  Back,
  Cancel,
}

export interface EditableLeftIconV2Options {
  iconType?: EditableLeftIconTypeV2;
  defaultFocus?: boolean;
  onAction?: () => void;
}

@ObservedV2
export class EditableLeftIconV2 {
  @Trace public iconType: EditableLeftIconTypeV2 = EditableLeftIconTypeV2.Back;
  @Trace public defaultFocus: boolean = false;
  @Trace public onAction?: () => void;

  constructor(options?: EditableLeftIconV2Options) {
    if (options) {
      if (options.iconType !== undefined) {
        this.iconType = options.iconType;
      }
      if (options.defaultFocus !== undefined) {
        this.defaultFocus = options.defaultFocus;
      }
      if (options.onAction !== undefined) {
        this.onAction = options.onAction;
      }
    }
  }
}

export interface EditableTitleV2Options {
  mainTitle?: ResourceStr;
  subTitle?: ResourceStr;
}

@ObservedV2
export class EditableTitleV2 {
  @Trace public mainTitle: ResourceStr = '';
  @Trace public subTitle?: ResourceStr;

  constructor(options?: EditableTitleV2Options) {
    if (options) {
      if (options.mainTitle !== undefined) {
        this.mainTitle = options.mainTitle;
      }
      if (options.subTitle !== undefined) {
        this.subTitle = options.subTitle;
      }
    }
  }
}

export interface EditableTitleBarMenuItemV2Options {
  value?: ResourceStr;
  symbolStyle?: SymbolGlyphModifier;
  isEnabled?: boolean;
  label?: ResourceStr;
  action?: () => void;
  accessibilityLevel?: string;
  accessibilityText?: ResourceStr;
  accessibilityDescription?: ResourceStr;
  defaultFocus?: boolean;
}

@ObservedV2
export class EditableTitleBarMenuItemV2 {
  @Trace public value: ResourceStr = '';
  @Trace public symbolStyle?: SymbolGlyphModifier;
  @Trace public isEnabled: boolean = true;
  @Trace public label?: ResourceStr;
  @Trace public action?: () => void;
  @Trace public accessibilityLevel: string = 'auto';
  @Trace public accessibilityText?: ResourceStr;
  @Trace public accessibilityDescription?: ResourceStr;
  @Trace public defaultFocus: boolean = false;

  constructor(options?: EditableTitleBarMenuItemV2Options) {
    if (options) {
      if (options.value !== undefined) {
        this.value = options.value;
      }
      if (options.symbolStyle !== undefined) {
        this.symbolStyle = options.symbolStyle;
      }
      if (options.isEnabled !== undefined) {
        this.isEnabled = options.isEnabled;
      }
      if (options.label !== undefined) {
        this.label = options.label;
      }
      if (options.action !== undefined) {
        this.action = options.action;
      }
      if (options.accessibilityLevel !== undefined) {
        this.accessibilityLevel = options.accessibilityLevel;
      }
      if (options.accessibilityText !== undefined) {
        this.accessibilityText = options.accessibilityText;
      }
      if (options.accessibilityDescription !== undefined) {
        this.accessibilityDescription = options.accessibilityDescription;
      }
      if (options.defaultFocus !== undefined) {
        this.defaultFocus = options.defaultFocus;
      }
    }
  }
}

export type EditableTitleBarItemV2 = EditableTitleBarMenuItemV2;

export interface EditableSaveButtonV2Options {
  isRequired?: boolean;
  defaultFocus?: boolean;
  onAction?: () => void;
}

@ObservedV2
export class EditableSaveButtonV2 {
  @Trace public isRequired: boolean = true;
  @Trace public defaultFocus: boolean = false;
  @Trace public onAction?: () => void;

  constructor(options?: EditableSaveButtonV2Options) {
    if (options) {
      if (options.isRequired !== undefined) {
        this.isRequired = options.isRequired;
      }
      if (options.defaultFocus !== undefined) {
        this.defaultFocus = options.defaultFocus;
      }
      if (options.onAction !== undefined) {
        this.onAction = options.onAction;
      }
    }
  }
}

export interface EditableTitleBarStyleV2Options {
  backgroundColor?: ResourceColor;
  backgroundBlurStyle?: BlurStyle;
  safeAreaTypes?: Array<SafeAreaType>;
  safeAreaEdges?: Array<SafeAreaEdge>;
  contentMargin?: LocalizedMargin;
}

@ObservedV2
export class EditableTitleBarStyleV2 {
  @Trace public backgroundColor?: ResourceColor;
  @Trace public backgroundBlurStyle?: BlurStyle;
  @Trace public safeAreaTypes?: Array<SafeAreaType>;
  @Trace public safeAreaEdges?: Array<SafeAreaEdge>;
  @Trace public contentMargin?: LocalizedMargin;

  constructor(options?: EditableTitleBarStyleV2Options) {
    if (options) {
      if (options.backgroundColor !== undefined) {
        this.backgroundColor = options.backgroundColor;
      }
      if (options.backgroundBlurStyle !== undefined) {
        this.backgroundBlurStyle = options.backgroundBlurStyle;
      }
      if (options.safeAreaTypes !== undefined) {
        this.safeAreaTypes = options.safeAreaTypes;
      }
      if (options.safeAreaEdges !== undefined) {
        this.safeAreaEdges = options.safeAreaEdges;
      }
      if (options.contentMargin !== undefined) {
        this.contentMargin = options.contentMargin;
      }
    }
  }
}

enum ItemType {
  Image,
  Icon,
  LeftIcon,
}

const PUBLIC_CANCEL = $r('sys.symbol.xmark');

const PUBLIC_OK = $r('sys.symbol.checkmark');

const PUBLIC_BACK = $r('sys.symbol.chevron_backward');

const PUBLIC_IMAGE_BACK = $r('sys.media.ohos_ic_compnent_titlebar_back');

const DEFAULT_TITLE_BAR_HEIGHT = 56;
const DEFAULT_TITLE_PADDING = 2;
const MAX_LINE_ONE = 1;
const MAX_LINES_TWO = 2;
const MAX_MAIN_TITLE_PERCENT = 0.65;
const MAX_SUB_TITLE_PERCENT = 0.35;
const MIN_SUBTITLE_SIZE = '10.0vp';
const TEXT_EDITABLE_DIALOG = '18.3fp';
const IMAGE_SIZE = '64vp';
const MAX_DIALOG = '256vp';
const MIN_DIALOG = '216vp';
const SYMBOL_SIZE = '24vp';
const SYMBOL_TITLE_SIZE = '64vp';
const TITLE_VP: number = 20;
const SUBTITLE_VP: number = 14;

const TITLE_F: number = getNumberByResource(125831095, TITLE_VP);
const SUBTITLE_F: number = getNumberByResource(125831097, SUBTITLE_VP);

const TITLE_F_VP: string = (TITLE_F > 0 ? TITLE_F : TITLE_VP) + 'vp';
const SUBTITLE_F_VP: string = (SUBTITLE_F > 0 ? SUBTITLE_F : SUBTITLE_VP) + 'vp';

const EVENT_FONT_SIZE_CHANGE = 20001;

@ObservedV2
class EditableTitleBarTheme {
  @Trace public iconColor: ResourceColor = $r('sys.color.titlebar_icon_color');
  @Trace public iconBackgroundColor: ResourceColor = $r('sys.color.titlebar_icon_background_color');
  @Trace public iconBackgroundPressedColor: ResourceColor = $r('sys.color.titlebar_icon_background_pressed_color');
  @Trace public iconBackgroundHoverColor: ResourceColor = $r('sys.color.titlebar_icon_background_hover_color');
  @Trace public iconBackgroundFocusOutlineColor: ResourceColor = $r('sys.color.titlebar_icon_background_focus_outline_color');
  @Trace public titleColor: ResourceColor = $r('sys.color.titlebar_title_tertiary_color');
  @Trace public subTitleColor: ResourceColor = $r('sys.color.titlebar_subheader_color');
}

class ButtonGestureModifier implements GestureModifier {
  public static readonly longPressTime: number = 500;
  public static readonly minFontSize: number = 1.75;
  public fontSize: number = 1;
  public maxFontSize: number = 3.2;
  public dialogId: number | null = null;
  public builder: () => void = () => {};

  constructor(dialogId: number | null, builder: () => void) {
    this.dialogId = dialogId;
    this.builder = builder;
  }

  applyGesture(event: UIGestureEvent): void {
    if (this.fontSize >= ButtonGestureModifier.minFontSize) {
      event.addGesture(
        new LongPressGestureHandler({ repeat: false, duration: ButtonGestureModifier.longPressTime })
          .onAction(() => {
            if (event) {
              promptAction.openCustomDialog({
                builder: this.builder,
                maskColor: Color.Transparent,
                isModal: true,
                backgroundBlurStyle: BlurStyle.COMPONENT_ULTRA_THICK,
                backgroundColor: Color.Transparent,
                shadow: ShadowStyle.OUTER_DEFAULT_LG,
                cornerRadius: $r('sys.float.corner_radius_level10'),
                width: this.fontSize === this.maxFontSize ? MAX_DIALOG : MIN_DIALOG,
              }).then((dialogId: number) => {
                this.dialogId = dialogId;
              }).catch((err: BusinessError) => {
                hilog.error(0x3900, 'EditableTitleBarV2', `Failed to open dialog, error: ${err.message}`);
              });
            }
          })
          .onActionEnd(() => {
            if (this.dialogId !== null) {
              promptAction.closeCustomDialog(this.dialogId);
              this.dialogId = null;
            }
          })
      )
    } else {
      event.clearGestures();
    }
  }
}

@ComponentV2
export struct EditableTitleBarV2 {
  @Param leftIcon?: EditableLeftIconV2 = undefined;
  @Param title: ResourceStr | EditableTitleV2 = new EditableTitleV2();
  @Param imageItem?: EditableTitleBarItemV2 = undefined;
  @Param menuItems?: Array<EditableTitleBarMenuItemV2> = undefined;
  @Param saveButton?: EditableSaveButtonV2 = undefined;
  @Param options: EditableTitleBarStyleV2 = new EditableTitleBarStyleV2();
  public static readonly maxCountOfExtraItems = 3;
  public static readonly maxOtherCountOfExtraItems = 2;
  public static readonly commonZero = 0;
  public static readonly noneColor = '#00000000';
  public static readonly defaultHeight: number = getNumberByResource(125831115, DEFAULT_TITLE_BAR_HEIGHT);
  public static readonly defaultTitlePadding: number = getNumberByResource(125830920, DEFAULT_TITLE_PADDING);
  public static readonly totalHeight: number =
    EditableTitleBarV2.defaultHeight === EditableTitleBarV2.commonZero ? DEFAULT_TITLE_BAR_HEIGHT :
      EditableTitleBarV2.defaultHeight;
  static readonly titlePadding: number =
    EditableTitleBarV2.defaultTitlePadding === EditableTitleBarV2.commonZero ?
      DEFAULT_TITLE_PADDING : EditableTitleBarV2.defaultTitlePadding;
  private static readonly maxMainTitleHeight =
    (EditableTitleBarV2.totalHeight - EditableTitleBarV2.titlePadding) * MAX_MAIN_TITLE_PERCENT;
  private static readonly maxSubTitleHeight =
    (EditableTitleBarV2.totalHeight - EditableTitleBarV2.titlePadding) * MAX_SUB_TITLE_PERCENT;
  private isFollowingSystemFontScale: boolean = false;
  private maxFontScale: number = 1;
  private systemFontScale?: number = 1;
  @Local editableTitleBarTheme: EditableTitleBarTheme = new EditableTitleBarTheme();
  @Local fontSize: number = 1;
  private callbackId: number | undefined = undefined;

  private getContentMargin(): LocalizedMargin {
    if (this.options.contentMargin) {
      return this.options.contentMargin;
    }
    return {
      start: LengthMetrics.resource($r('sys.float.margin_left')),
      end: LengthMetrics.resource($r('sys.float.margin_right')),
    };
  }

  onWillApplyTheme(theme: Theme): void {
    this.editableTitleBarTheme.iconColor = theme.colors.iconPrimary;
    this.editableTitleBarTheme.titleColor = theme.colors.fontPrimary;
    this.editableTitleBarTheme.subTitleColor = theme.colors.fontSecondary;
    this.editableTitleBarTheme.iconBackgroundPressedColor = theme.colors.interactivePressed;
    this.editableTitleBarTheme.iconBackgroundHoverColor = theme.colors.interactiveHover;
    this.editableTitleBarTheme.iconBackgroundFocusOutlineColor = theme.colors.interactiveFocus;
  }

  aboutToAppear(): void {
    try {
      let uiContent: UIContext = this.getUIContext();
      this.isFollowingSystemFontScale = uiContent.isFollowingSystemFontScale();
      this.maxFontScale = uiContent.getMaxFontScale();
    } catch (exception) {
      let code: number = (exception as BusinessError)?.code;
      let message: string = (exception as BusinessError)?.message;
      hilog.error(0x3900, 'Ace', `Faild to init fontsizescale info,cause, code: ${code}, message: ${message}`);
    }
    emitter.on({ eventId: EVENT_FONT_SIZE_CHANGE }, (eventData: emitter.EventData) => {
      if (eventData.data && eventData.data.fontSize !== undefined) {
        this.fontSize = eventData.data.fontSize;
      }
    });
  }

  aboutToDisappear(): void {
    emitter.off(EVENT_FONT_SIZE_CHANGE);
    if (this.callbackId) {
      this.getUIContext()?.getHostContext()?.getApplicationContext()?.off('environment', this.callbackId);
    }
  }

  decideFontScale(): number {
    let uiContent: UIContext = this.getUIContext();
    this.systemFontScale = (uiContent.getHostContext() as common.UIAbilityContext)?.config?.fontSizeScale ?? 1;
    if (!this.isFollowingSystemFontScale) {
      return 1;
    }
    return Math.min(this.systemFontScale, this.maxFontScale);
  }

  build() {
    Flex({
      justifyContent: FlexAlign.SpaceBetween,
      alignItems: ItemAlign.Stretch,
    }) {
      Row() {
        Row() {
          if (this.leftIcon) {
            this.leftIconLayout();
          }
        }
        .flexShrink(0)

        Row() {
          if (this.imageItem) {
            Row() {
              this.imageItemLayout();
            }
            .flexShrink(0)
          }

          Row() {
            this.titleLayout();
          }
          .width('100%')
          .flexShrink(1)
        }
        .width('100%')
        .flexShrink(1)
        .accessibilityGroup(true)
        .accessibilityDescription($r('sys.string.subheader_accessibility_title'))

        Row() {
          this.rightMenuItemsLayout();
        }
        .flexShrink(0)
      }
      .width('100%')
      .margin(this.getContentMargin())
      .height(EditableTitleBarV2.totalHeight)
    }
    .backgroundColor(this.options.backgroundColor ?? EditableTitleBarV2.noneColor)
    .backgroundBlurStyle(
      this.options.backgroundBlurStyle ?? BlurStyle.NONE, undefined, { disableSystemAdaptation: true })
    .expandSafeArea(
      this.options.safeAreaTypes ? this.options.safeAreaTypes : [SafeAreaType.SYSTEM],
      this.options.safeAreaEdges ? this.options.safeAreaEdges : [SafeAreaEdge.TOP],
    )
  }

  @Builder
  imageItemLayout(): void {
    ImageMenuItem({
      item: this.imageItem!,
      attribute: ItemType.Image,
      editableTitleBarTheme: this.editableTitleBarTheme,
    })
  }

  @Builder
  leftIconLayout(): void {
    if (this.leftIcon!.iconType === EditableLeftIconTypeV2.Back) {
      ImageMenuItem({
        item: new EditableTitleBarMenuItemV2({
          value: PUBLIC_BACK,
          isEnabled: true,
          action: this.leftIcon!.onAction ? this.leftIcon!.onAction : () => this.getUIContext()?.getRouter()?.back(),
          defaultFocus: this.leftIcon!.defaultFocus
        }),
        fontSize: this.fontSize,
        attribute: ItemType.LeftIcon,
        imageMenuItemId: `BackMenuItem_${this.getUniqueId()}`,
        editableTitleBarTheme: this.editableTitleBarTheme,
      })
    } else {
      ImageMenuItem({
        item: new EditableTitleBarMenuItemV2({
          value: PUBLIC_CANCEL,
          isEnabled: true,
          action: this.leftIcon!.onAction ? this.leftIcon!.onAction : () => {},
          defaultFocus: this.leftIcon!.defaultFocus
        }),
        fontSize: this.fontSize,
        attribute: ItemType.LeftIcon,
        imageMenuItemId: `CancelMenuItem_${this.getUniqueId()}`,
        editableTitleBarTheme: this.editableTitleBarTheme,
      })
    }
  }

  private isTitleConfig(title: ResourceStr | EditableTitleV2): boolean {
    return title instanceof EditableTitleV2;
  }

  private getMainTitle(): ResourceStr {
    if (typeof this.title === 'string') {
      return this.title;
    }
    if (this.isTitleConfig(this.title)) {
      return (this.title as EditableTitleV2).mainTitle;
    }
    return this.title as Resource;
  }

  private getSubTitle(): ResourceStr | undefined {
    if (typeof this.title === 'string') {
      return undefined;
    }
    if (this.isTitleConfig(this.title)) {
      return (this.title as EditableTitleV2).subTitle;
    }
    return undefined;
  }

  @Builder
  titleLayout(): void {
    Column() {
      Row() {
        Text(this.getMainTitle())
          .maxFontSize(TITLE_F_VP)
          .minFontSize(SUBTITLE_F_VP)
          .fontColor(this.editableTitleBarTheme.titleColor)
          .maxLines(this.getSubTitle() ? MAX_LINE_ONE : MAX_LINES_TWO)
          .fontWeight(FontWeight.Bold)
          .textAlign(TextAlign.Start)
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .heightAdaptivePolicy(this.getSubTitle() ?
            TextHeightAdaptivePolicy.MAX_LINES_FIRST : TextHeightAdaptivePolicy.MIN_FONT_SIZE_FIRST)
          .constraintSize({
            maxHeight: this.getSubTitle() ? EditableTitleBarV2.maxMainTitleHeight : EditableTitleBarV2.totalHeight,
          })
      }
      .justifyContent(FlexAlign.Start)

      if (this.getSubTitle()) {
        Row() {
          Text(this.getSubTitle()!)
            .maxFontSize(SUBTITLE_F_VP)
            .minFontSize(MIN_SUBTITLE_SIZE)
            .fontColor(this.editableTitleBarTheme.subTitleColor)
            .maxLines(MAX_LINE_ONE)
            .fontWeight(FontWeight.Regular)
            .textAlign(TextAlign.Start)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .heightAdaptivePolicy(TextHeightAdaptivePolicy.MAX_LINES_FIRST)
            .constraintSize({
              maxHeight: this.getMainTitle() ? EditableTitleBarV2.maxSubTitleHeight : EditableTitleBarV2.totalHeight,
            })
        }
        .margin({
          top: $r('sys.float.padding_level1'),
        })
        .justifyContent(FlexAlign.Start)
      }
    }
    .height(EditableTitleBarV2.totalHeight)
    .justifyContent(FlexAlign.Center)
    .margin({
      start: LengthMetrics.resource($r('sys.float.titlebar_icon_background_space_horizontal')),
    })
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  rightMenuItemsLayout(): void {
    EditableTitleBarMenuSection({
      menuItems: this.menuItems,
      saveButton: this.saveButton,
      fontSize: this.fontSize,
      parentUniqueId: this.getUniqueId(),
      editableTitleBarTheme: this.editableTitleBarTheme,
    })
  }

  onPlaceChildren(selfLayoutInfo: GeometryInfo, children: Layoutable[], constraint: ConstraintSizeOptions): void {
    children.forEach((child) => {
      child.layout({ x: 0, y: 0 });
    })
  }

  onMeasureSize(selfLayoutInfo: GeometryInfo, children: Measurable[], constraint: ConstraintSizeOptions): SizeResult {
    let result: SizeResult = { width: selfLayoutInfo.width, height: selfLayoutInfo.height };
    this.fontSize = this.decideFontScale();
    emitter.emit({ eventId: EVENT_FONT_SIZE_CHANGE }, { data: { fontSize: this.fontSize } });
    children.forEach((child) => {
      result.height = child.measure(constraint).height;
      result.width = Number(constraint.maxWidth);
    })
    return result;
  }
}

@ComponentV2
struct EditableTitleBarMenuSection {
  @Param menuItems?: Array<EditableTitleBarMenuItemV2> = undefined;
  @Param saveButton?: EditableSaveButtonV2 = undefined;
  @Param fontSize: number = 1;
  @Param parentUniqueId?: number = undefined;
  @Param editableTitleBarTheme: EditableTitleBarTheme = new EditableTitleBarTheme();

  private getIsRequired(): boolean {
    if (this.saveButton) {
      return this.saveButton.isRequired;
    }
    return true;
  }

  private getDefaultFocus(): boolean {
    if (this.saveButton) {
      return this.saveButton.defaultFocus;
    }
    return false;
  }

  private getOnAction(): (() => void) | undefined {
    if (this.saveButton) {
      return this.saveButton.onAction;
    }
    return undefined;
  }

  build() {
    Column() {
      Row() {
        if (this.menuItems !== undefined && this.menuItems.length > EditableTitleBarV2.commonZero) {
          ForEach(this.menuItems.slice(EditableTitleBarV2.commonZero,
            this.getIsRequired() ?
              EditableTitleBarV2.maxOtherCountOfExtraItems : EditableTitleBarV2.maxCountOfExtraItems),
            (item: EditableTitleBarMenuItemV2, index: number) => {
              ImageMenuItem({
                item: item,
                attribute: ItemType.Icon,
                imageMenuItemId: `ImageMenuItem_${this.parentUniqueId}_${index}`,
                editableTitleBarTheme: this.editableTitleBarTheme,
              })
            })
        }
        if (this.getIsRequired()) {
          ImageMenuItem({
            item: new EditableTitleBarMenuItemV2({
              value: PUBLIC_OK,
              isEnabled: true,
              action: this.getOnAction() ? this.getOnAction() : () => {},
              defaultFocus: this.getDefaultFocus()
            }),
            fontSize: this.fontSize,
            attribute: ItemType.Icon,
            imageMenuItemId: `SaveMenuItem_${this.parentUniqueId}`,
            editableTitleBarTheme: this.editableTitleBarTheme,
          })
        }
      }
    }
    .justifyContent(FlexAlign.Center)
  }
}

@ComponentV2
struct ImageMenuItem {
  @Param item: EditableTitleBarMenuItemV2 = new EditableTitleBarMenuItemV2();
  @Param attribute: ItemType = ItemType.Image;
  callbackId: number | undefined = undefined;
  minFontSize: number = 1.75;
  maxFontSize: number = 3.2;
  longPressTime: number = 500;
  systemFontScale?: number = 1;
  isFollowingSystemFontScale: boolean = false;
  maxFontScale: number = 1;
  @Param fontSize: number = 1;
  @Local innerFontSize: number = 1;
  @Local isOnFocus: boolean = false;
  @Local isOnHover: boolean = false;
  @Local isOnClick: boolean = false;
  @Param imageMenuItemId?: string = undefined;
  @Param editableTitleBarTheme: EditableTitleBarTheme = new EditableTitleBarTheme();
  dialogId: number | null = null;
  @Local buttonGestureModifier: ButtonGestureModifier | null = null;

  aboutToAppear() {
    try {
      let uiContent: UIContext = this.getUIContext();
      this.isFollowingSystemFontScale = uiContent.isFollowingSystemFontScale();
      this.maxFontScale = uiContent.getMaxFontScale();
    } catch (exception) {
      let code: number = (exception as BusinessError)?.code;
      let message: string = (exception as BusinessError)?.message;
      hilog.error(0x3900, 'Ace', `Faild to init fontsizescale info,cause, code: ${code}, message: ${message}`);
    }

    this.buttonGestureModifier = new ButtonGestureModifier(this.dialogId, () => {
      this.EditableTitleBarDialogBuilder();
    });

    try {
      this.callbackId =
        this.getUIContext()?.getHostContext()?.getApplicationContext()?.on('environment', this.envCallback);
    } catch (paramError) {
      let code = (paramError as BusinessError)?.code;
      let message = (paramError as BusinessError)?.message;
      hilog.error(0x3900, 'EditableTitleBarV2',
        `Failed to get environment param error: ${code}, ${message}`);
    }
    this.innerFontSize = this.decideFontScale();
    if (this.buttonGestureModifier) {
      this.buttonGestureModifier.fontSize = this.innerFontSize;
      this.buttonGestureModifier.maxFontSize = this.maxFontSize;
    }
  }

  aboutToDisappear(): void {
    if (this.callbackId) {
      this.getUIContext()?.getHostContext()?.getApplicationContext()?.off('environment', this.callbackId);
      this.callbackId = undefined;
    }
  }

  private textDialog(): ResourceStr {
    if (this.item.value === PUBLIC_OK) {
      return $r('sys.string.icon_save');
    } else if (this.item.value === PUBLIC_CANCEL) {
      return $r('sys.string.icon_cancel');
    } else if (this.item.value === PUBLIC_BACK) {
      return $r('sys.string.icon_back');
    } else {
      return this.item.label ? this.item.label : '';
    }
  }

  private envCallback: EnvironmentCallback = {
    onConfigurationUpdated: (config) => {
      if (config === undefined || !this.isFollowingSystemFontScale) {
        this.innerFontSize = 1;
        return;
      }
      try {
        this.innerFontSize = Math.min(
          this.maxFontScale, config?.fontSizeScale ?? 1);
        if (this.buttonGestureModifier) {
          this.buttonGestureModifier.fontSize = this.innerFontSize;
        }
      } catch (paramError) {
        let code = (paramError as BusinessError)?.code;
        let message = (paramError as BusinessError)?.message;
        hilog.error(0x3900, 'EditableTitleBarV2',
          `EnvironmentCallback error: ${code}, ${message}`);
      }
    },
    onMemoryLevel: (level) => {
    }
  }

  decideFontScale(): number {
    try {
      let uiContent: UIContext = this.getUIContext();
      this.systemFontScale = (uiContent?.getHostContext() as common.UIAbilityContext)?.config?.fontSizeScale ?? 1;
      if (!this.isFollowingSystemFontScale) {
        return 1;
      }
      return Math.min(this.systemFontScale, this.maxFontScale);
    } catch (exception) {
      let code: number = (exception as BusinessError)?.code;
      let message: string = (exception as BusinessError)?.message;
      hilog.error(0x3900, 'EditableTitleBarV2', `Failed to decideFontScale,cause, code: ${code}, message: ${message}`);
      return 1;
    }
  }

  @Styles
  buttonStateStyles() {
    .stateStyles({
      focused: this.focusedStyle,
      normal: this.notInFocusedStyle,
      pressed: this.notInFocusedStyle,
    })
  }

  @Styles
  focusedStyle() {
    .border({
      radius: $r('sys.float.titlebar_icon_background_shape'),
      width: $r('sys.float.titlebar_icon_background_focus_outline_weight'),
      color: this.editableTitleBarTheme.iconBackgroundFocusOutlineColor,
      style: BorderStyle.Solid,
    })
  }

  @Styles
  notInFocusedStyle() {
    .border({
      radius: $r('sys.float.titlebar_icon_background_shape'),
      width: EditableTitleBarV2.commonZero,
    })
  }

  private touchEventAction(event: TouchEvent): void {
    if (!this.item.isEnabled) {
      return;
    }
    if (event.type === TouchType.Down) {
      this.isOnClick = true;
    }
    if (event.type === TouchType.Up || event.type === TouchType.Cancel) {
      if (this.innerFontSize >= this.minFontSize && this.dialogId !== null) {
        promptAction.closeCustomDialog(this.dialogId);
        this.dialogId = null;
      }
      this.isOnClick = false;
    }
  }

  private keyEventAction(event: KeyEvent): void {
    if (!this.item.isEnabled) {
      return;
    }
    if (event.keyCode !== KeyCode.KEYCODE_ENTER && event.keyCode !== KeyCode.KEYCODE_SPACE) {
      return;
    }
    if (event.type === KeyType.Down) {
      this.isOnClick = true;
    }
    if (event.type === KeyType.Up) {
      this.isOnClick = false;
    }
  }

  @Styles
  buttonEventStyle() {
    .onFocus(() => {
      if (!this.item.isEnabled) {
        return;
      }
      this.isOnFocus = true;
    })
    .onBlur(() => this.isOnFocus = false)
    .onHover((isOn) => {
      if (!this.item.isEnabled) {
        return;
      }
      this.isOnHover = isOn;
    })
    .onKeyEvent((event) => {
      this.keyEventAction(event);
    })
    .onTouch((event) => {
      this.touchEventAction(event);
    })
    .onClick(() => {
      if (this.item.isEnabled === undefined) {
        this.item.isEnabled = true;
      }
      this.item.isEnabled && this.item.action && this.item.action()
    })
  }

  @Styles
  backgroundButtonStyle() {
    .width($r('sys.float.titlebar_icon_background_width'))
    .height($r('sys.float.titlebar_icon_background_height'))
    .focusable(this.item.isEnabled)
    .enabled(this.item.isEnabled)
  }

  getBgColor(): ResourceColor {
    if (this.isOnClick) {
      return this.editableTitleBarTheme.iconBackgroundPressedColor;
    } else if (this.isOnHover) {
      return this.editableTitleBarTheme.iconBackgroundHoverColor;
    } else {
      return this.editableTitleBarTheme.iconBackgroundColor;
    }
  }

  getFgColor(): ResourceStr {
    if (this.isOnClick) {
      return $r('sys.color.titlebar_icon_background_pressed_color');
    } else if (this.isOnHover) {
      return $r('sys.color.titlebar_icon_background_hover_color');
    } else {
      return EditableTitleBarV2.noneColor;
    }
  }

  getStringByNameSync(contextName: string): string {
    let uiContext: string = '';
    try {
      uiContext = getContext()?.resourceManager?.getStringByNameSync(contextName);
    } catch (exception) {
      let code: number = (exception as BusinessError)?.code;
      let message: string = (exception as BusinessError)?.message;
      hilog.error(0x3900, 'Ace', `Faild to getStringByNameSync,cause, code: ${code}, message: ${message}`);
    }
    return uiContext;
  }

  private toStringFormat(resource: ResourceStr | undefined): string | undefined {
    if (typeof resource === 'string' || typeof resource === 'undefined') {
      return resource;
    } else {
      let resourceString: string = '';
      try {
        if (resource.id === -1) {
          resourceString = getContext()?.resourceManager?.getStringByNameSync(resource.params?.[0]?.split('.').pop() ?? '');
        } else {
          resourceString = getContext()?.resourceManager?.getStringSync(resource);
        }
      } catch (err) {
        let code: number = (err as BusinessError)?.code;
        let message: string = (err as BusinessError)?.message;
        hilog.error(0x3900, 'Ace', `Faild to EditableTitleBarV2 toStringFormat, code: ${code}, message: ${message}`)
      }
      return resourceString;
    }
  }

  private getAccessibilityReadText(): string | undefined {
    if (this.item.value === PUBLIC_OK) {
      return this.getStringByNameSync('icon_save');
    } else if (this.item.value === PUBLIC_CANCEL) {
      return this.getStringByNameSync('icon_cancel');
    } else if (this.item.value === PUBLIC_BACK) {
      return this.getStringByNameSync('icon_back');
    } else if (this.item.accessibilityText) {
      return this.item.accessibilityText as string;
    } else if (this.item.label) {
      return this.item.label as string;
    }
    return ' ';
  }

  private getRightIconAccessibilityLevel(): string {
    if (this.item.accessibilityLevel && this.item.accessibilityLevel !== '') {
      return this.item.accessibilityLevel;
    }
    return 'auto';
  }

  private getAccessibilityDescription(): string | undefined {
    if (this.item.accessibilityDescription && this.item.accessibilityDescription !== '') {
      return this.item.accessibilityDescription as string;
    }
    return '';
  }

  @Builder
  EditableTitleBarDialogBuilder(): void {
    EditableTitleBarDialogContent({
      itemEditableDialog: this.item,
      textEditableTitleBarDialog: this.item.label ? this.item.label : this.textDialog(),
      fontSize: this.fontSize,
    })
  }

  @Builder
  IconBuilder(): void {
    Button({ type: ButtonType.Normal, stateEffect: this.item.isEnabled }) {
      if (this.item.symbolStyle !== undefined) {
        SymbolGlyph()
          .fontColor([this.editableTitleBarTheme.iconColor])
          .attributeModifier(this.item.symbolStyle)
          .focusable(this.item.isEnabled)
          .enabled(this.item.isEnabled)
          .draggable(false)
          .accessibilityText(this.getAccessibilityReadText())
          .effectStrategy(SymbolEffectStrategy.NONE)
          .symbolEffect(new SymbolEffect(), false)
          .fontSize(SYMBOL_SIZE)
      } else {
        if (Util.isSymbolResource(this.item.value)) {
          SymbolGlyph(this.item.value as Resource)
            .fontSize(SYMBOL_SIZE)
            .fontColor([this.editableTitleBarTheme.iconColor])
            .focusable(this.item.isEnabled)
            .enabled(this.item.isEnabled)
            .draggable(false)
            .accessibilityText(this.getAccessibilityReadText())
        } else {
          Image(this.item.value)
            .fillColor(this.editableTitleBarTheme.iconColor)
            .matchTextDirection(this.item.value === PUBLIC_IMAGE_BACK ? true : false)
            .width($r('sys.float.titlebar_icon_width'))
            .height($r('sys.float.titlebar_icon_height'))
            .focusable(this.item.isEnabled)
            .enabled(this.item.isEnabled)
            .draggable(false)
            .accessibilityText(this.getAccessibilityReadText())
        }
      }
    }
    .id(this.imageMenuItemId)
    .backgroundButtonStyle()
    .borderRadius($r('sys.float.titlebar_icon_background_shape'))
    .margin({
      start: this.attribute === ItemType.LeftIcon ? LengthMetrics.vp(EditableTitleBarV2.commonZero) :
        LengthMetrics.resource($r('sys.float.titlebar_icon_background_space_horizontal')),
    })
    .focusOnTouch(true)
    .foregroundColor(this.getFgColor())
    .backgroundColor(this.getBgColor())
    .buttonStateStyles()
    .buttonEventStyle()
    .gestureModifier(this.buttonGestureModifier!)
    .accessibilityLevel(this.getRightIconAccessibilityLevel())
    .accessibilityDescription(this.getAccessibilityDescription())
    .defaultFocus(this.item.defaultFocus)
  }

  @Builder
  ImageBuilder() {
    Stack({ alignContent: Alignment.Center }) {
      Image(this.item.value)
        .width($r('sys.float.titlebar_icon_background_width'))
        .height($r('sys.float.titlebar_icon_background_height'))
        .borderRadius($r('sys.float.corner_radius_level10'))
        .focusable(false)
        .enabled(this.item.isEnabled)
        .objectFit(ImageFit.Cover)
      Button({ type: ButtonType.Circle })
        .backgroundButtonStyle()
        .foregroundColor(this.getFgColor())
        .backgroundColor(EditableTitleBarV2.noneColor)
        .buttonStateStyles()
        .buttonEventStyle()
        .gestureModifier(this.buttonGestureModifier!)
        .defaultFocus(this.item.defaultFocus)
    }
    .margin({
      start: LengthMetrics.resource($r('sys.float.titlebar_icon_background_space_horizontal')),
    })
  }

  build() {
    if (this.attribute === ItemType.Icon || this.attribute === ItemType.LeftIcon) {
      this.IconBuilder();
    } else {
      this.ImageBuilder();
    }
  }
}

@ComponentV2
struct EditableTitleBarDialogContent {
  @Param itemEditableDialog: EditableTitleBarMenuItemV2 = new EditableTitleBarMenuItemV2();
  callbackId: number | undefined = undefined;
  @Param textEditableTitleBarDialog?: ResourceStr = '';
  mainWindowStage: window.Window | undefined = undefined;
  minFontSize: number = 1.75;
  maxFontSize: number = 3.2;
  screenWidth: number = 640;
  verticalScreenLines: number = 6;
  horizontalsScreenLines: number = 1;
  mainWindow: window.Window | undefined = undefined;
  @Param fontSize: number = 1;
  @Local maxLines: number = 1;
  windowStandardHeight: number = 0;

  build() {
    if (this.textEditableTitleBarDialog) {
      Column() {
        if (this.itemEditableDialog.symbolStyle !== undefined) {
          SymbolGlyph()
            .fontColor([$r('sys.color.icon_primary')])
            .attributeModifier(this.itemEditableDialog.symbolStyle)
            .margin({
              top: $r('sys.float.padding_level24'),
              bottom: $r('sys.float.padding_level8'),
            })
            .effectStrategy(SymbolEffectStrategy.NONE)
            .symbolEffect(new SymbolEffect(), false)
            .fontSize(SYMBOL_TITLE_SIZE)
            .direction(Direction.Ltr)
        } else {
          if (Util.isSymbolResource(this.itemEditableDialog.value)) {
            SymbolGlyph(this.itemEditableDialog.value as Resource)
              .margin({
                top: $r('sys.float.padding_level24'),
                bottom: $r('sys.float.padding_level8'),
              })
              .fontColor([$r('sys.color.icon_primary')])
              .fontSize(SYMBOL_TITLE_SIZE)
              .direction(Direction.Ltr)
          } else {
            Image(this.itemEditableDialog.value)
              .width(IMAGE_SIZE)
              .height(IMAGE_SIZE)
              .margin({
                top: $r('sys.float.padding_level24'),
                bottom: $r('sys.float.padding_level8'),
              })
              .fillColor($r('sys.color.icon_primary'))
              .direction(Direction.Ltr)
          }
        }
        Column() {
          Text(this.textEditableTitleBarDialog)
            .fontSize(TEXT_EDITABLE_DIALOG)
            .textOverflow({ overflow: TextOverflow.Ellipsis })
            .maxLines(this.maxLines)
            .width('100%')
            .textAlign(TextAlign.Center)
            .fontColor($r('sys.color.font_primary'))
        }
        .width('100%')
        .padding({
          left: $r('sys.float.padding_level4'),
          right: $r('sys.float.padding_level4'),
          bottom: $r('sys.float.padding_level12'),
        })
      }
      .width(this.fontSize === this.maxFontSize ? MAX_DIALOG : MIN_DIALOG)
      .constraintSize({ minHeight: this.fontSize === this.maxFontSize ? MAX_DIALOG : MIN_DIALOG })
      .backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, undefined, { disableSystemAdaptation: true })
      .shadow(ShadowStyle.OUTER_DEFAULT_LG)
      .borderRadius(($r('sys.float.corner_radius_level10')))
    } else {
      Column() {
        if (this.itemEditableDialog.symbolStyle !== undefined) {
          SymbolGlyph()
            .fontColor([$r('sys.color.icon_primary')])
            .attributeModifier(this.itemEditableDialog.symbolStyle)
            .effectStrategy(SymbolEffectStrategy.NONE)
            .symbolEffect(new SymbolEffect(), false)
            .fontSize(SYMBOL_TITLE_SIZE)
        } else {
          if (Util.isSymbolResource(this.itemEditableDialog.value)) {
            SymbolGlyph(this.itemEditableDialog.value as Resource)
              .fontColor([$r('sys.color.icon_primary')])
              .fontSize(SYMBOL_TITLE_SIZE)
          } else {
            Image(this.itemEditableDialog.value)
              .width(IMAGE_SIZE)
              .height(IMAGE_SIZE)
              .fillColor($r('sys.color.icon_primary'))
          }
        }
      }
      .width(this.fontSize === this.maxFontSize ? MAX_DIALOG : MIN_DIALOG)
      .constraintSize({ minHeight: this.fontSize === this.maxFontSize ? MAX_DIALOG : MIN_DIALOG })
      .backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, undefined, { disableSystemAdaptation: true })
      .shadow(ShadowStyle.OUTER_DEFAULT_LG)
      .borderRadius(($r('sys.float.corner_radius_level10')))
      .justifyContent(FlexAlign.Center)
      .direction(Direction.Ltr)
    }
  }

  async aboutToAppear(): Promise<void> {
    try {
      let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
      this.mainWindowStage = context.windowStage.getMainWindowSync();
    } catch (error) {
      let code: number = (error as BusinessError)?.code;
      let message: string = (error as BusinessError)?.message;
      hilog.error(0x3900, 'Ace', `EditableTitleBarV2 getMainWindowStage error, code: ${code},message:${message}`);
      return;
    }
    if (this.mainWindowStage) {
      let properties: window.WindowProperties = this.mainWindowStage.getWindowProperties();
      let rect = properties.windowRect;
      if (px2vp(rect.height) > this.screenWidth) {
        this.maxLines = this.verticalScreenLines;
      } else {
        this.maxLines = this.horizontalsScreenLines;
      }
    }
  }
}

function getNumberByResource(resourceId: number, defaultNumber: number): number {
  try {
    let resourceNumber: number = resourceManager.getSystemResourceManager().getNumber(resourceId);
    if (resourceNumber === 0) {
      return defaultNumber;
    } else {
      return resourceNumber;
    }
  } catch (error) {
    let code: number = (error as BusinessError).code;
    let message: string = (error as BusinessError).message;
    hilog.error(0x3900, 'Ace', `EditableTitleBarV2 getNumberByResource error, code: ${code},message:${message}`);
    return 0;
  }
}

class Util {
  private static RESOURCE_TYPE_SYMBOL = 40000;

  public static isSymbolResource(resourceStr: ResourceStr | undefined): boolean {
    if (!Util.isResourceType(resourceStr)) {
      return false;
    }
    let resource = resourceStr as Resource;
    return resource.type === Util.RESOURCE_TYPE_SYMBOL;
  }

  public static isResourceType(resource: ResourceStr | Resource | undefined): boolean {
    if (!resource) {
      return false;
    }
    if (typeof resource === 'string' || typeof resource === 'undefined') {
      return false;
    }
    return true;
  }
}