/*
 * Copyright (c) 2025-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 {
  ColorMetrics,
  curves,
  ImageModifier,
  LengthMetrics,
  LengthUnit,
  SymbolGlyphModifier,
  TextModifier,
  UIContext,
} from '@kit.ArkUI';
import { SizeT } from '@ohos.arkui.node';
import { i18n } from '@kit.LocalizationKit';
import util from '@ohos.util';
import uiMaterial from '@ohos.arkui.uiMaterial';
import { EnvironmentCallback, common } from '@kit.AbilityKit';
import deviceInfo from '@ohos.deviceInfo';

export interface SegmentButtonV2ItemOptions {
  text?: ResourceStr;
  icon?: ResourceStr;
  symbol?: Resource;
  enabled?: boolean;
  textModifier?: TextModifier;
  iconModifier?: ImageModifier;
  symbolModifier?: SymbolGlyphModifier;
  accessibilityText?: ResourceStr;
  accessibilityDescription?: ResourceStr;
  accessibilityLevel?: string;
}

export type OnSelectedIndexChange = (selectedIndex: number) => void;

export type OnSelectedIndexesChange = (selectedIndexes: number[]) => void;

interface SegmentButtonV2ContentTheme {
  itemSpace: LengthMetrics;
  itemFontSize: Dimension;
  adaptiveItemFontSize: Dimension;
  itemFontColor: ResourceColor;
  itemFontWeight: FontWeight;
  itemSelectedFontWeight: FontWeight;
  itemSelectedFontColor: ResourceColor;
  itemIconSize: Dimension;
  itemIconFillColor: ResourceColor;
  itemSelectedIconFillColor: ResourceColor;
  itemSymbolFontSize: Dimension;
  itemSymbolFontColor: ResourceColor;
  itemSelectedSymbolFontColor: ResourceColor;
  itemMinHeight: Dimension;
  hybridItemMinHeight: Dimension;
  itemPadding: LocalizedPadding;
  itemMaxFontScale: number | Resource;
  itemMaxFontScaleSmallest: number;
  itemMaxFontScaleLargest: number;
  itemMinFontScale: number | Resource;
  itemMinFontScaleSmallest: number;
  itemMinFontScaleLargest: number;
}

interface SimpleSegmentButtonV2Theme extends SegmentButtonV2ContentTheme {
  buttonBackgroundColor: Resource;
  buttonBorderRadius: Resource;
  buttonMinHeight: Dimension;
  hybridButtonMinHeight: Dimension;
  buttonPadding: Resource;
  itemSelectedBackgroundColor: ResourceColor;
  itemBorderRadius: Resource;
}

interface SegmentButtonV2ItemRect {
  size: SizeT<number>;
  position: PositionT<number>;
  globalPosition: PositionT<number>;
}

const SMALLEST_MAX_FONT_SCALE: number = 1;
const LARGEST_MAX_FONT_SCALE: number = 2;
const SMALLEST_MIN_FONT_SCALE: number = 0;
const LARGEST_MIN_FONT_SCALE: number = 1;
const COLOR_RESOURCE_TYPE: number = 10001;

const tabSimpleTheme: SimpleSegmentButtonV2Theme = {
  buttonBackgroundColor: $r('sys.color.segment_button_v2_tab_button_background'),
  buttonBorderRadius: $r('sys.float.segment_button_v2_background_corner_radius'),
  buttonMinHeight: $r('sys.float.segment_button_v2_singleline_background_height'),
  hybridButtonMinHeight: $r('sys.float.segment_button_v2_doubleline_background_height'),
  buttonPadding: $r('sys.float.padding_level1'),
  itemSelectedBackgroundColor: $r('sys.color.segment_button_v2_tab_selected_item_background'),
  itemBorderRadius: $r('sys.float.segment_button_v2_selected_corner_radius'),
  itemSpace: LengthMetrics.vp(0),
  itemFontSize: $r('sys.float.ohos_id_text_size_button2'),
  adaptiveItemFontSize: $r('sys.float.Caption_M'),
  itemFontColor: $r('sys.color.font_secondary'),
  itemSelectedFontColor: $r('sys.color.font_primary'),
  itemFontWeight: FontWeight.Medium,
  itemSelectedFontWeight: FontWeight.Medium,
  itemIconSize: 24,
  itemIconFillColor: $r('sys.color.font_secondary'),
  itemSelectedIconFillColor: $r('sys.color.font_primary'),
  itemSymbolFontSize: 20,
  itemSymbolFontColor: $r('sys.color.font_secondary'),
  itemSelectedSymbolFontColor: $r('sys.color.font_primary'),
  itemMinHeight: $r('sys.float.segment_button_v2_singleline_selected_height'),
  hybridItemMinHeight: $r('sys.float.segment_button_v2_doubleline_selected_height'),
  itemPadding: {
    top: LengthMetrics.resource($r('sys.float.padding_level2')),
    bottom: LengthMetrics.resource($r('sys.float.padding_level2')),
    start: LengthMetrics.resource($r('sys.float.padding_level4')),
    end: LengthMetrics.resource($r('sys.float.padding_level4')),
  },
  itemMaxFontScale: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleSmallest: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleLargest: LARGEST_MAX_FONT_SCALE,
  itemMinFontScale: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleSmallest: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleLargest: LARGEST_MIN_FONT_SCALE,
};

const capsuleSimpleTheme: SimpleSegmentButtonV2Theme = {
  buttonBackgroundColor: $r('sys.color.segment_button_v2_tab_button_background'),
  buttonBorderRadius: $r('sys.float.segment_button_v2_background_corner_radius'),
  buttonMinHeight: $r('sys.float.segment_button_v2_singleline_background_height'),
  hybridButtonMinHeight: $r('sys.float.segment_button_v2_doubleline_background_height'),
  buttonPadding: $r('sys.float.padding_level1'),
  itemSelectedBackgroundColor: $r('sys.color.comp_background_emphasize'),
  itemBorderRadius: $r('sys.float.segment_button_v2_selected_corner_radius'),
  itemSpace: LengthMetrics.vp(0),
  itemFontSize: $r('sys.float.ohos_id_text_size_button2'),
  adaptiveItemFontSize: $r('sys.float.Caption_M'),
  itemFontColor: $r('sys.color.font_secondary'),
  itemSelectedFontColor: $r('sys.color.font_on_primary'),
  itemFontWeight: FontWeight.Medium,
  itemSelectedFontWeight: FontWeight.Medium,
  itemIconSize: 24,
  itemIconFillColor: $r('sys.color.icon_secondary'),
  itemSelectedIconFillColor: $r('sys.color.font_on_primary'),
  itemSymbolFontSize: 20,
  itemSymbolFontColor: $r('sys.color.font_secondary'),
  itemSelectedSymbolFontColor: $r('sys.color.font_on_primary'),
  itemMinHeight: $r('sys.float.segment_button_v2_singleline_selected_height'),
  hybridItemMinHeight: $r('sys.float.segment_button_v2_doubleline_selected_height'),
  itemPadding: {
    top: LengthMetrics.resource($r('sys.float.padding_level2')),
    bottom: LengthMetrics.resource($r('sys.float.padding_level2')),
    start: LengthMetrics.resource($r('sys.float.padding_level4')),
    end: LengthMetrics.resource($r('sys.float.padding_level4')),
  },
  itemMaxFontScale: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleSmallest: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleLargest: LARGEST_MAX_FONT_SCALE,
  itemMinFontScale: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleSmallest: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleLargest: LARGEST_MIN_FONT_SCALE,
}

@ObservedV2
export class SegmentButtonV2Item {
  @Trace text?: ResourceStr;
  @Trace icon?: ResourceStr;
  @Trace symbol?: Resource;
  @Trace enabled: boolean;
  @Trace textModifier?: TextModifier;
  @Trace iconModifier?: ImageModifier;
  @Trace symbolModifier?: SymbolGlyphModifier;
  @Trace accessibilityText?: ResourceStr;
  @Trace accessibilityDescription?: ResourceStr;
  @Trace accessibilityLevel?: string;

  constructor(options: SegmentButtonV2ItemOptions) {
    this.text = options.text;
    this.icon = options.icon;
    this.symbol = options.symbol;
    this.enabled = options.enabled ?? true;
    this.textModifier = options.textModifier;
    this.iconModifier = options.iconModifier;
    this.symbolModifier = options.symbolModifier;
    this.accessibilityText = options.accessibilityText;
    this.accessibilityDescription = options.accessibilityDescription;
    this.accessibilityLevel = options.accessibilityLevel;
  }

  @Computed
  get isHybrid(): boolean {
    return !!this.text && (!!this.icon || !!this.symbol);
  }
}

@ObservedV2
export class SegmentButtonV2Items extends Array<SegmentButtonV2Item> {
  constructor(length: number);

  constructor(items: SegmentButtonV2ItemOptions[]);

  constructor(lengthOrItemOptionsArray: number | SegmentButtonV2ItemOptions[]) {
    super(typeof lengthOrItemOptionsArray === 'number' ? lengthOrItemOptionsArray : 0);

    if (typeof lengthOrItemOptionsArray !== 'number' && lengthOrItemOptionsArray && lengthOrItemOptionsArray.length) {
      for (let options of lengthOrItemOptionsArray) {
        if (options) {
          this.push(new SegmentButtonV2Item(options))
        }
      }
    }
  }

  @Computed
  get hasHybrid(): boolean {
    return this.some((item) => item.isHybrid);
  }
}

const EMPTY_ITEMS = new SegmentButtonV2Items([]);

@ComponentV2
export struct TabSegmentButtonV2 {
  @Require
  @Param
  items: SegmentButtonV2Items;
  @Require
  @Param
  selectedIndex: number;
  @Event
  $selectedIndex?: OnSelectedIndexChange;
  @Event
  onItemClicked?: Callback<number>;
  @Param
  itemMinFontScale?: number | Resource = undefined;
  @Param
  itemMaxFontScale?: number | Resource = undefined;
  @Param
  itemSpace?: LengthMetrics = undefined;
  @Param
  itemFontSize?: LengthMetrics = undefined;
  @Param
  itemSelectedFontSize?: LengthMetrics = undefined;
  @Param
  itemFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedFontColor?: ColorMetrics = undefined;
  @Param
  itemFontWeight?: FontWeight = undefined;
  @Param
  itemSelectedFontWeight?: FontWeight = undefined;
  @Param
  itemBorderRadius?: LengthMetrics = undefined;
  @Param
  itemSelectedBackgroundColor?: ColorMetrics = undefined;
  @Param
  itemIconSize?: SizeT<LengthMetrics> = undefined;
  @Param
  itemIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSelectedIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSymbolFontSize?: LengthMetrics = undefined;
  @Param
  itemSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemMinHeight?: LengthMetrics = undefined;
  @Param
  itemPadding?: LocalizedPadding = undefined;
  @Param
  itemShadow?: ShadowOptions | ShadowStyle = undefined;
  @Param
  buttonBackgroundColor?: ColorMetrics = undefined;
  @Param
  buttonBackgroundBlurStyle?: BlurStyle = undefined;
  @Param
  buttonBackgroundBlurStyleOptions?: BackgroundBlurStyleOptions = undefined;
  @Param
  buttonBackgroundEffect?: BackgroundEffectOptions = undefined;
  @Param
  buttonBorderRadius?: LengthMetrics = undefined;
  @Param
  buttonMinHeight?: LengthMetrics = undefined;
  @Param
  buttonPadding?: LengthMetrics = undefined;
  @Param
  languageDirection?: Direction = undefined;
  @Param
  backgroundSystemMaterial?: uiMaterial.Material = undefined;
  @Param
  enableStateAnimation?: boolean = false

  build() {
    SimpleSegmentButtonV2({
      theme: tabSimpleTheme,
      items: this.items,
      selectedIndex: this.selectedIndex,
      $selectedIndex: (selectedIndex) => {
        this.$selectedIndex?.(selectedIndex);
      },
      onItemClicked: this.onItemClicked,
      itemMinFontScale: this.itemMinFontScale,
      itemMaxFontScale: this.itemMaxFontScale,
      itemSpace: this.itemSpace,
      itemFontColor: this.itemFontColor,
      itemSelectedFontColor: this.itemSelectedFontColor,
      itemFontSize: this.itemFontSize,
      itemSelectedFontSize: this.itemSelectedFontSize,
      itemFontWeight: this.itemFontWeight,
      itemSelectedFontWeight: this.itemSelectedFontWeight,
      itemSelectedBackgroundColor: this.itemSelectedBackgroundColor,
      itemIconSize: this.itemIconSize,
      itemIconFillColor: this.itemIconFillColor,
      itemSelectedIconFillColor: this.itemSelectedIconFillColor,
      itemSymbolFontSize: this.itemSymbolFontSize,
      itemSymbolFontColor: this.itemSymbolFontColor,
      itemSelectedSymbolFontColor: this.itemSelectedSymbolFontColor,
      itemBorderRadius: this.itemBorderRadius,
      itemMinHeight: this.itemMinHeight,
      itemPadding: this.itemPadding,
      itemShadow: this.itemShadow,
      buttonBackgroundColor: this.buttonBackgroundColor,
      buttonBackgroundBlurStyle: this.buttonBackgroundBlurStyle,
      buttonBackgroundBlurStyleOptions: this.buttonBackgroundBlurStyleOptions,
      buttonBackgroundEffect: this.buttonBackgroundEffect,
      buttonBorderRadius: this.buttonBorderRadius,
      buttonMinHeight: this.buttonMinHeight,
      buttonPadding: this.buttonPadding,
      languageDirection: this.languageDirection,
      backgroundSystemMaterial: this.backgroundSystemMaterial,
      enableStateAnimation: this.enableStateAnimation
    })
  }
}

@ComponentV2
export struct CapsuleSegmentButtonV2 {
  @Require
  @Param
  items: SegmentButtonV2Items;
  @Require
  @Param
  selectedIndex: number;
  @Event
  $selectedIndex?: OnSelectedIndexChange;
  @Event
  onItemClicked?: Callback<number>;
  @Param
  itemMinFontScale?: number | Resource = undefined;
  @Param
  itemMaxFontScale?: number | Resource = undefined;
  @Param
  itemSpace?: LengthMetrics = undefined;
  @Param
  itemFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedFontColor?: ColorMetrics = undefined;
  @Param
  itemFontSize?: LengthMetrics = undefined;
  @Param
  itemSelectedFontSize?: LengthMetrics = undefined;
  @Param
  itemFontWeight?: FontWeight = undefined;
  @Param
  itemSelectedFontWeight?: FontWeight = undefined;
  @Param
  itemBorderRadius?: LengthMetrics = undefined;
  @Param
  itemSelectedBackgroundColor?: ColorMetrics = undefined;
  @Param
  itemIconSize?: SizeT<LengthMetrics> = undefined;
  @Param
  itemIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSelectedIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSymbolFontSize?: LengthMetrics = undefined;
  @Param
  itemSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemMinHeight?: LengthMetrics = undefined;
  @Param
  itemPadding?: LocalizedPadding = undefined;
  @Param
  itemShadow?: ShadowOptions | ShadowStyle = undefined;
  @Param
  buttonBackgroundColor?: ColorMetrics = undefined;
  @Param
  buttonBackgroundBlurStyle?: BlurStyle = undefined;
  @Param
  buttonBackgroundBlurStyleOptions?: BackgroundBlurStyleOptions = undefined;
  @Param
  buttonBackgroundEffect?: BackgroundEffectOptions = undefined;
  @Param
  buttonBorderRadius?: LengthMetrics = undefined;
  @Param
  buttonMinHeight?: LengthMetrics = undefined;
  @Param
  buttonPadding?: LengthMetrics = undefined;
  @Param
  languageDirection?: Direction = undefined;
  @Param
  backgroundSystemMaterial?: uiMaterial.Material = undefined;
  @Param
  enableStateAnimation?: boolean = false

  build() {
    SimpleSegmentButtonV2({
      theme: capsuleSimpleTheme,
      items: this.items,
      selectedIndex: this.selectedIndex,
      $selectedIndex: (selectedIndex) => {
        this.$selectedIndex?.(selectedIndex);
      },
      onItemClicked: this.onItemClicked,
      itemMinFontScale: this.itemMinFontScale,
      itemMaxFontScale: this.itemMaxFontScale,
      itemSpace: this.itemSpace,
      itemFontColor: this.itemFontColor,
      itemSelectedFontColor: this.itemSelectedFontColor,
      itemFontSize: this.itemFontSize,
      itemSelectedFontSize: this.itemSelectedFontSize,
      itemFontWeight: this.itemFontWeight,
      itemSelectedFontWeight: this.itemSelectedFontWeight,
      itemSelectedBackgroundColor: this.itemSelectedBackgroundColor,
      itemIconSize: this.itemIconSize,
      itemIconFillColor: this.itemIconFillColor,
      itemSelectedIconFillColor: this.itemSelectedIconFillColor,
      itemSymbolFontSize: this.itemSymbolFontSize,
      itemSymbolFontColor: this.itemSymbolFontColor,
      itemSelectedSymbolFontColor: this.itemSelectedSymbolFontColor,
      itemBorderRadius: this.itemBorderRadius,
      itemMinHeight: this.itemMinHeight,
      itemPadding: this.itemPadding,
      itemShadow: this.itemShadow,
      buttonBackgroundColor: this.buttonBackgroundColor,
      buttonBackgroundBlurStyle: this.buttonBackgroundBlurStyle,
      buttonBackgroundBlurStyleOptions: this.buttonBackgroundBlurStyleOptions,
      buttonBackgroundEffect: this.buttonBackgroundEffect,
      buttonBorderRadius: this.buttonBorderRadius,
      buttonMinHeight: this.buttonMinHeight,
      buttonPadding: this.buttonPadding,
      languageDirection: this.languageDirection,
      backgroundSystemMaterial: this.backgroundSystemMaterial,
      enableStateAnimation: this.enableStateAnimation
    })
  }
}

@ComponentV2
struct SimpleSegmentButtonV2 {
  @Require
  @Param
  items: SegmentButtonV2Items;
  @Require
  @Param
  selectedIndex: number;
  @Event
  $selectedIndex?: OnSelectedIndexChange;
  @Require
  @Param
  theme: SimpleSegmentButtonV2Theme;
  @Event
  onItemClicked?: Callback<number>;
  @Require
  @Param
  itemMinFontScale?: number | Resource = undefined;
  @Require
  @Param
  itemMaxFontScale?: number | Resource = undefined;
  @Require
  @Param
  itemSpace?: LengthMetrics = undefined;
  @Require
  @Param
  itemFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemSelectedFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemFontWeight?: FontWeight = undefined;
  @Require
  @Param
  itemSelectedFontWeight?: FontWeight = undefined;
  @Require
  @Param
  itemBorderRadius?: LengthMetrics = undefined;
  @Require
  @Param
  itemSelectedBackgroundColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemIconSize?: SizeT<LengthMetrics> = undefined;
  @Require
  @Param
  itemIconFillColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedIconFillColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSymbolFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemSymbolFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedSymbolFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemMinHeight?: LengthMetrics = undefined;
  @Require
  @Param
  itemPadding?: LocalizedPadding = undefined;
  @Require
  @Param
  itemShadow?: ShadowOptions | ShadowStyle = undefined;
  @Require
  @Param
  buttonBackgroundColor?: ColorMetrics = undefined;
  @Require
  @Param
  buttonBackgroundBlurStyle?: BlurStyle = undefined;
  @Require
  @Param
  buttonBackgroundBlurStyleOptions?: BackgroundBlurStyleOptions = undefined;
  @Require
  @Param
  buttonBackgroundEffect?: BackgroundEffectOptions = undefined;
  @Require
  @Param
  buttonBorderRadius?: LengthMetrics = undefined;
  @Require
  @Param
  buttonMinHeight?: LengthMetrics = undefined;
  @Require
  @Param
  buttonPadding?: LengthMetrics = undefined;
  @Require
  @Param
  languageDirection?: Direction = undefined;
  @Require
  @Param
  backgroundSystemMaterial?: uiMaterial.Material = undefined;
  @Local
  itemRects: SegmentButtonV2ItemRect[] = [];
  @Local
  itemScale: number = 1;
  @Local
  hoveredItemIndex: number = -1;
  @Local
  mousePressedItemIndex: number = -1;
  @Local
  touchPressedItemIndex: number = -1;
  private isMouseWheelScroll: boolean = false;
  private isDragging: boolean = false;
  private isPressing: boolean = false;
  private panStartGlobalX: number = 0;
  private panStartIndex: number = -1;
  private dragWithPress: boolean = false;
  private focusGroupId: string = GroupIdGenerator.getInstance().generate();
  @Param enableStateAnimation?: boolean = false
  @Local openSelectedItemSystemMaterial?: boolean = false;
  @Local selectedItemScale?: ScaleOptions;
  @Local tempDisableAnimation?: boolean = false;
  @Local backplatePosition: Position = {x: 0, y: 0};

  @Computed
  get normalizedSelectedIndex(): number {
    const items = this.getItems();
    return normalize(this.selectedIndex, 0, items.length - 1);
  }

  @Computed
  get selectedItemRect(): SegmentButtonV2ItemRect | undefined {
    return this.itemRects[this.normalizedSelectedIndex];
  }

  @LocalBuilder
  private ContentLayer() {
    Flex({ alignItems: ItemAlign.Stretch, space: { main: this.getItemSpace() } }) {
      Repeat(this.getItems())
        .each((repeatItem: RepeatItem<SegmentButtonV2Item>) => {
          Button({ type: ButtonType.Normal }) {
            SegmentButtonV2ItemContent({
              theme: this.theme,
              item: repeatItem.item,
              selected: this.isSelected(repeatItem),
              itemMinFontScale: this.itemMinFontScale,
              itemMaxFontScale: this.itemMaxFontScale,
              itemFontColor: this.itemFontColor,
              itemSelectedFontColor: this.itemSelectedFontColor,
              itemFontSize: this.itemFontSize,
              itemSelectedFontSize: this.itemSelectedFontSize,
              itemFontWeight: this.itemFontWeight,
              itemSelectedFontWeight: this.itemSelectedFontWeight,
              itemIconSize: this.itemIconSize,
              itemIconFillColor: this.itemIconFillColor,
              itemSelectedIconFillColor: this.itemSelectedIconFillColor,
              itemSymbolFontSize: this.itemSymbolFontSize,
              itemSymbolFontColor: this.itemSymbolFontColor,
              itemSelectedSymbolFontColor: this.itemSelectedSymbolFontColor,
              itemMinHeight: this.itemMinHeight,
              itemPadding: this.itemPadding,
              languageDirection: this.languageDirection,
              hasHybrid: this.getItems().hasHybrid,
            })
          }
          .accessibilityGroup(true)
          .accessibilitySelected(this.isSelected(repeatItem))
          .accessibilityText(this.getItemAccessibilityText(repeatItem))
          .accessibilityDescription(this.getItemAccessibilityDescription(repeatItem))
          .accessibilityLevel(repeatItem.item.accessibilityLevel)
          .backgroundColor(Color.Transparent)
          .borderRadius(this.getItemBorderRadius())
          .direction(this.languageDirection)
          .enabled(repeatItem.item.enabled)
          .focusScopePriority(this.focusGroupId, this.getFocusPriority(repeatItem))
          .hoverEffect(HoverEffect.None)
          .layoutWeight(1)
          .padding(0)
          .scale(this.getItemScale(repeatItem.index))
          .stateEffect(false)
          .onAreaChange((_, area) => {
            this.itemRects[repeatItem.index] = {
              size: {
                width: area.width as number,
                height: area.height as number,
              },
              position: {
                x: area.position.x as number,
                y: area.position.y as number,
              },
              globalPosition: {
                x: area.globalPosition.x as number,
                y: area.globalPosition.y as number,
              }
            };
          })
          .gesture(
            TapGesture().onAction(() => {
              this.onItemClicked?.(repeatItem.index);
              this.backplatePosition = {
                x: this.selectedItemRect?.position.x,
                y: this.selectedItemRect?.position.y
              }
              this.updateSelectedIndex(repeatItem.index);
            })
          )
          .onTouch((event) => {
            if (event.type === TouchType.Down) {
              if (this.isSelected(repeatItem)) {
                this.updateItemScale(0.95);
              }
              this.updateTouchPressedItemIndex(repeatItem.index);
            } else if ([TouchType.Up, TouchType.Cancel].includes(event.type)) {
              this.updateItemScale(1)
              this.updateTouchPressedItemIndex(-1);
            }
          })
          .onHover((isHover) => {
            if (isHover) {
              this.updateHoveredItemIndex(repeatItem.index);
            } else {
              this.updateHoveredItemIndex(-1);
            }
          })
          .onMouse((event) => {
            if (event.action === MouseAction.Press) {
              this.updateMousePressedItemIndex(repeatItem.index);
            } else if ([MouseAction.Release, MouseAction.CANCEL].includes(event.action)) {
              this.updateMousePressedItemIndex(-1);
            }
          })
        })
        .key(generateUniqueKye(this.focusGroupId))
    }
    .constraintSize({
      minWidth: '100%',
      minHeight: this.getButtonMinHeight()
    })
    .clip(false)
    .direction(this.languageDirection)
    .focusScopeId(this.focusGroupId, true)
    .padding(this.getButtonPadding())
    .accessibilityLevel('no')
    .priorityGesture(GestureGroup(GestureMode.Parallel,
      LongPressGesture({ repeat: false, duration: 200 })
        .onAction((event: GestureEvent) => {
          if (!this.isBackgroundSystemMaterialEnabled()) {
            return
          }
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          const index = this.getIndexByPosition(finger.localX, finger.localY);
          if (!this.isItemEnabled(index)) {
            return;
          }
          if (index === this.normalizedSelectedIndex) {
            this.isPressing = true;
          }
          if (this.isPressing && !this.openSelectedItemSystemMaterial) {
            this.startSelectMaterialAnimation();
          }
        })
        .onActionCancel((event: GestureEvent) => {
          if (!this.isBackgroundSystemMaterialEnabled()) {
            return
          }
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          if (!this.isDragging && this.isPressing && this.openSelectedItemSystemMaterial) {
            this.finishSelectMaterialAnimation();
          }
          this.isPressing = false;
        })
        .onActionEnd((event: GestureEvent) => {
          if (!this.isBackgroundSystemMaterialEnabled()) {
            return
          }
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          if (!this.isDragging && this.openSelectedItemSystemMaterial) {
            this.finishSelectMaterialAnimation();
          }
          this.isPressing = false;
        }),
      PanGesture()
        .onActionStart((event) => {
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          const index = this.getIndexByPosition(finger.localX, finger.localY);
          if (!this.isItemEnabled(index)) {
            return;
          }
          if (event.axisHorizontal !== 0 || event.axisVertical !== 0) {
            this.isMouseWheelScroll = true;
            return;
          }
          if (index === this.normalizedSelectedIndex) {
            this.isDragging = true;
          }
          if (this.isPressing) {
            this.dragWithPress = true;
          }
          this.panStartGlobalX = finger.localX;
          this.panStartIndex = index;

          if (this.isBackgroundSystemMaterialEnabled() && this.isDragging) {
            this.backplatePosition = {
              x: this.selectedItemRect!.position.x,
              y: this.selectedItemRect!.position.y
            }
            if (!this.dragWithPress) {
              this.getUIContext().animateTo({
                curve: curves.interpolatingSpring(0, 1, 195, 14),
              }, () => {
                this.openSelectedItemSystemMaterial = true;
              })
            }
            this.getUIContext().animateTo({
              curve: curves.interpolatingSpring(0, 1, 195, 14),
              delay: 300
            }, () => {
              this.selectedItemScale = { x: 1.01, y: 0.99 }
            })
          }
        })
        .onActionUpdate((event) => {
          if (!this.isDragging) {
            return;
          }
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          if (this.isBackgroundSystemMaterialEnabled()) {
            let nowX = finger.localX - this.panStartGlobalX + this.selectedItemRect!.position.x as number;
            let startX = this.itemRects[0]!.position.x as number;
            let endX = this.itemRects[this.items.length - 1]!.position.x as number;
            if (this.isRTL()) {
              startX = this.itemRects[this.items.length - 1]!.position.x as number;
              endX = this.itemRects[0]!.position.x as number
            }
            nowX = Math.max(startX, nowX);
            nowX = Math.min(endX, nowX);

            this.backplatePosition = {
              x: nowX,
              y: this.backplatePosition!.y
            }
          } else {
            const index = this.getIndexByPosition(finger.localX, finger.localY);
            this.updateSelectedIndex(index);
          }
        })
        .onActionEnd((event) => {
          if (!this.isItemEnabled(this.panStartIndex)) {
            return;
          }
          // handle mouse wheel scroll event
          if (this.isMouseWheelScroll) {
            const offset = event.offsetX !== 0 ? event.offsetX : event.offsetY;
            const deltaIndex = offset < 0 ? 1 : -1;
            this.updateSelectedIndex(this.normalizedSelectedIndex + deltaIndex);
            this.isMouseWheelScroll = false;
            return;
          }
          // handle drag event
          if (this.isDragging) {
            if (this.isBackgroundSystemMaterialEnabled()) {
              const finger = event.fingerList.find(Boolean);
              if (!finger) {
                return;
              }
              let realIndex = -1;
              let selectedInfo = finger.localX
              for (let i = 0; i < this.items.length; i++) {
                selectedInfo = selectedInfo - (this.itemRects[i].size.width as number)
                if (selectedInfo < 0) {
                  realIndex = this.isRTL() ? this.items.length - 1 - i : i;
                  break
                }
              }
              if (realIndex === -1) {
                realIndex = this.isRTL() ? 0 : this.items.length - 1;
              }
              this.tempDisableAnimation = true;
              this.getUIContext().animateTo({ curve: curves.springMotion(0.347, 0.99) }, () => {
                this.$selectedIndex?.(realIndex);
                this.backplatePosition = {
                  x: this.itemRects[realIndex].position.x,
                  y: this.itemRects[realIndex].position.y
                }
              })
              if (!this.dragWithPress) {
                this.getUIContext().animateTo({
                  curve: curves.interpolatingSpring(0, 1, 195, 14),
                  onFinish: () => {
                    this.tempDisableAnimation = false
                  }
                }, () => {
                  this.openSelectedItemSystemMaterial = false;
                  this.selectedItemScale = undefined
                })
              } else {
                this.finishSelectMaterialAnimation();
              }
            }
            this.isDragging = false;
            this.dragWithPress = false;
            return;
          }
          // handle swipe event
          if (!this.isItemEnabled(this.normalizedSelectedIndex)) {
            return;
          }
          const finger = event.fingerList.find(Boolean);
          if (!finger) {
            return;
          }
          let deltaIndex = finger.localX - this.panStartGlobalX < 0 ? -1 : 1;
          if (this.isRTL()) {
            deltaIndex = -deltaIndex;
          }
          this.updateSelectedIndex(this.normalizedSelectedIndex + deltaIndex);
        })
        .onActionCancel(() => {
          this.isDragging = false;
          this.isMouseWheelScroll = false;
          this.panStartIndex = -1;
          this.dragWithPress = false;
          if (!this.dragWithPress) {
            this.getUIContext().animateTo({
              curve: curves.interpolatingSpring(0, 1, 195, 14),
              onFinish: () => {
                this.tempDisableAnimation = false
              }
            }, () => {
              this.openSelectedItemSystemMaterial = false;
              this.selectedItemScale = undefined
            })
          } else {
            this.finishSelectMaterialAnimation();
          }
        })
    )
    )
  }

  private getFocusPriority(repeatItem: RepeatItem<SegmentButtonV2Item>): FocusPriority | undefined {
    return this.normalizedSelectedIndex === repeatItem.index ? FocusPriority.PREVIOUS : FocusPriority.AUTO;
  }

  private getSystemMaterial(inputMaterial: uiMaterial.Material | undefined): uiMaterial.Material | undefined {
    let info = uiMaterial.getMaterialInfo();
    if (info.state === uiMaterial.MaterialState.ENABLE && !inputMaterial) {
      return new uiMaterial.ImmersiveMaterial({
        style: uiMaterial.ImmersiveStyle.THIN
      });
    } else if (info.state === uiMaterial.MaterialState.DISABLE) {
      return undefined;
    }
    return inputMaterial;
  }

  startSelectMaterialAnimation() {
    this.backplatePosition = {
      x: this.selectedItemRect!.position.x,
      y: this.selectedItemRect!.position.y
    }
    if (!this.openSelectedItemSystemMaterial) {
      this.getUIContext().animateTo({
        curve: curves.interpolatingSpring(0, 1, 195, 14),
      }, () => {
        this.selectedItemScale = { x: 1.05, y: 1.18 }
        this.openSelectedItemSystemMaterial = true;
      })
    }
  }

  finishSelectMaterialAnimation() {
    if (this.openSelectedItemSystemMaterial) {
      this.tempDisableAnimation = true;
      this.getUIContext().animateTo({ curve: curves.interpolatingSpring(0, 1, 195, 14) }, () => {
        this.selectedItemScale = { x: 1.05, y: 1.18 }
      })
      this.getUIContext()
        .animateTo({
          curve: curves.interpolatingSpring(0, 1, 195, 14), delay: 300, onFinish: () => {
            this.tempDisableAnimation = false
          }
        }, () => {
          this.openSelectedItemSystemMaterial = false
          this.selectedItemScale = undefined
        })
    }
  }

  private isBackgroundSystemMaterialEnabled(): boolean {
    return this.backgroundSystemMaterial !== undefined;
  }

  private isItemEnabled(index: number): boolean {
    const items = this.getItems();
    if (index < 0 || index >= items.length) {
      return false;
    }
    return items[index].enabled;
  }

  @LocalBuilder
  private BackplateLayer() {
    if (this.selectedItemRect) {
      Stack()
        .position(this.getBackplatePosition())
        .animation((!this.tempDisableAnimation && this.enableStateAnimation) ?
          { curve: curves.springMotion(0.347, 0.99) } : undefined)
        .backgroundColor(this.getItemSelectedBackgroundColor())
        .borderRadius(this.getItemBorderRadius())
        .scale(this.getBackplateScale())
        .opacity(this.getBackplateOpacity())
        .shadow(this.getItemBackplateShadow())
        .height(this.selectedItemRect.size.height)
        .width(this.selectedItemRect.size.width)
    }
  }

  getBackplatePosition() {
    if (this.openSelectedItemSystemMaterial) {
      return this.backplatePosition;
    } else {
      return {
        x: this.selectedItemRect!.position.x,
        y: this.selectedItemRect!.position.y,
      } as Position;
    }
  }

  getBackplateOpacity() {
    if (this.openSelectedItemSystemMaterial) {
      return 0.7;
    } else {
      return 1;
    }
  }

  getBackplateScale(): ScaleOptions | undefined {
    if (this.openSelectedItemSystemMaterial) {
      return this.selectedItemScale;
    } else {
      return { x: this.itemScale, y: this.itemScale };
    }
  }

  @LocalBuilder
  EffectLayer() {
    Repeat(this.getItemRects())
      .each((repeatItem) => {
        Stack()
          .backgroundColor(this.getEffectBackgroundColor(repeatItem))
          .borderRadius(this.getItemBorderRadius())
          .height(repeatItem.item.size.height)
          .position({
            x: repeatItem.item.position.x,
            y: repeatItem.item.position.y
          })
          .scale(this.getItemScale(repeatItem.index))
          .width(repeatItem.item.size.width)
      })
  }

  private getItemRects(): SegmentButtonV2ItemRect[] {
    if (!this.items) {
      return [];
    }
    if (this.items.length === this.itemRects.length) {
      return this.itemRects;
    }

    return this.itemRects.slice(0, this.items.length);
  }

  build() {
    Stack() {
      Stack() {
        this.EffectLayer()
        this.BackplateLayer()
        this.ContentLayer()
      }
      .borderRadius(this.getButtonBorderRadius())
      .backgroundBlurStyle(this.getButtonBackgroundBlurStyle(), this.getButtonBackgroundBlurStyleOptions(),
        { disableSystemAdaptation: true })
      .clip(false)
      .direction(this.languageDirection)
    }
    .backgroundColor(this.getButtonBackgroundColor())
    .systemMaterial(this.getSystemMaterial(this.backgroundSystemMaterial))
    .backgroundEffect(this.buttonBackgroundEffect, { disableSystemAdaptation: true })
    .borderRadius(this.getButtonBorderRadius())
    .clip(false)
    .constraintSize({
      minWidth: '100%',
      minHeight: this.getButtonMinHeight()
    })
    .direction(this.languageDirection)
  }

  private getItems(): SegmentButtonV2Items {
    return this.items ?? EMPTY_ITEMS;
  }

  private getItemBackplateShadow(): ShadowOptions | ShadowStyle | undefined {
    return this.itemShadow;
  }

  private getButtonBackgroundBlurStyle(): BlurStyle | undefined {
    if (this.buttonBackgroundEffect) {
      return undefined;
    }
    return this.buttonBackgroundBlurStyle;
  }

  private getButtonBackgroundBlurStyleOptions(): BackgroundBlurStyleOptions | undefined {
    if (this.buttonBackgroundEffect) {
      return undefined;
    }
    return this.buttonBackgroundBlurStyleOptions;
  }

  private getItemScale(index: number): ScaleOptions {
    const pressed: boolean = this.isPressed(index);
    const scale: number = pressed ? 0.95 : 1;
    return { x: scale, y: scale, };
  }

  private isPressed(index: number): boolean {
    return this.mousePressedItemIndex === index;
  }

  private updateHoveredItemIndex(index: number) {
    if (index === this.hoveredItemIndex) {
      return;
    }
    animateTo({ duration: 250, curve: Curve.Friction }, () => {
      this.hoveredItemIndex = index;
    });
  }

  private updateMousePressedItemIndex(index: number) {
    if (index === this.mousePressedItemIndex) {
      return;
    }
    animateTo({ duration: 250, curve: Curve.Friction }, () => {
      this.mousePressedItemIndex = index;
    });
  }

  private updateTouchPressedItemIndex(index: number) {
    if (index === this.touchPressedItemIndex) {
      return;
    }
    animateTo({ duration: 250, curve: Curve.Friction }, () => {
      this.touchPressedItemIndex = index;
    });
  }

  private isRTL(): boolean {
    if (!this.languageDirection || this.languageDirection === Direction.Auto) {
      return i18n.isRTL(i18n.System.getSystemLanguage());
    }
    return this.languageDirection === Direction.Rtl;
  }

  private getEffectBackgroundColor(repeatItem: RepeatItem<SegmentButtonV2ItemRect>): ResourceColor {
    if (repeatItem.index === this.mousePressedItemIndex) {
      return $r('sys.color.interactive_click');
    }
    if (repeatItem.index === this.hoveredItemIndex) {
      return $r('sys.color.interactive_hover');
    }
    return Color.Transparent;
  }

  private getItemBorderRadius(): Length | BorderRadiuses | LocalizedBorderRadiuses {
    if (this.itemBorderRadius && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemBorderRadius)) {
      return LengthMetricsUtils.getInstance().stringify(this.itemBorderRadius);
    }
    return this.theme.itemBorderRadius;

  }

  private getItemSelectedBackgroundColor(): ResourceColor {
    if (this.itemSelectedBackgroundColor) {
      return this.itemSelectedBackgroundColor.color;
    }
    return this.theme.itemSelectedBackgroundColor;
  }

  getItemSpace(): LengthMetrics {
    if (this.itemSpace && this.itemSpace.unit !== LengthUnit.PERCENT
      && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemSpace)) {
      return this.itemSpace;
    }
    return this.theme.itemSpace;
  }

  getIndexByPosition(globalX: number, globalY: number): number {
    let index = 0;
    while (index < this.itemRects.length) {
      const rect = this.itemRects[index];
      if (this.isPointOnRect(globalX, globalY, rect)) {
        return index;
      }
      ++index;
    }
    return -1;
  }

  private isPointOnRect(localX: number, localY: number, rect: SegmentButtonV2ItemRect): boolean {
    return localX >= rect.position.x && localX <= rect.position.x + rect.size.width &&
      localY >= rect.position.y && localY <= rect.position.y + rect.size.height;
  }

  private updateSelectedIndex(selectedIndex: number) {
    if (!this.isItemEnabled(selectedIndex) || selectedIndex === this.selectedIndex
    ) {
      return;
    }

    if (this.isBackgroundSystemMaterialEnabled() && !this.tempDisableAnimation) {
      this.getUIContext().animateTo({
        curve: curves.interpolatingSpring(0, 1, 195, 14),
      }, () => {
        this.selectedItemScale = { x: 1.01, y: 0.99 }
        this.openSelectedItemSystemMaterial = true;
      })
    }

    this.getUIContext().animateTo({ curve: curves.springMotion(0.347, 0.99) }, () => {
      this.$selectedIndex?.(selectedIndex);
      this.backplatePosition = {
        x: this.itemRects[selectedIndex].position.x,
        y: this.itemRects[selectedIndex].position.y
      }
    });

    if (this.isBackgroundSystemMaterialEnabled() && !this.tempDisableAnimation) {
      this.getUIContext().animateTo({
        curve: curves.interpolatingSpring(0, 1, 195, 14),
        delay: 250
      }, () => {
        this.openSelectedItemSystemMaterial = false;
      });
    }
  }

  private updateItemScale(scale: number) {
    if (this.itemScale === scale) {
      return;
    }
    this.getUIContext().animateTo({ curve: curves.interpolatingSpring(10, 1, 410, 38) }, () => {
      this.itemScale = scale;
    });
  }

  private getItemAccessibilityDescription(repeatItem: RepeatItem<SegmentButtonV2Item>): string | undefined {
    return repeatItem.item.accessibilityDescription as ESObject as string;
  }

  private getItemAccessibilityText(repeatItem: RepeatItem<SegmentButtonV2Item>): string | undefined {
    return repeatItem.item.accessibilityText as ESObject as string;
  }

  private isSelected(repeatItem: RepeatItem<SegmentButtonV2Item>): boolean | undefined {
    return repeatItem.index === this.normalizedSelectedIndex;
  }

  private getButtonPadding(): Length | Padding | LocalizedPadding {
    if (this.buttonPadding && LengthMetricsUtils.getInstance().isNaturalNumber(this.buttonPadding)) {
      return LengthMetricsUtils.getInstance().stringify(this.buttonPadding);
    }
    return this.theme.buttonPadding;
  }

  private getButtonBorderRadius(): Length | BorderRadiuses | LocalizedBorderRadiuses {
    if (this.buttonBorderRadius && LengthMetricsUtils.getInstance().isNaturalNumber(this.buttonBorderRadius)) {
      return LengthMetricsUtils.getInstance().stringify(this.buttonBorderRadius);
    }
    return this.theme.buttonBorderRadius;
  }

  private getButtonBackgroundColor(): ResourceColor {
    if (this.buttonBackgroundColor) {
      return this.buttonBackgroundColor.color;
    }
    return this.theme.buttonBackgroundColor;
  }

  private getButtonMinHeight(): Dimension {
    if (this.buttonMinHeight && LengthMetricsUtils.getInstance().isNaturalNumber(this.buttonMinHeight)) {
      return LengthMetricsUtils.getInstance().stringify(this.buttonMinHeight);
    }
    const items = this.getItems();
    return items.hasHybrid ? this.theme.hybridButtonMinHeight : this.theme.buttonMinHeight;
  }
}

interface MultiplySegmentButtonV2Theme extends SegmentButtonV2ContentTheme {
  itemBackgroundColor: ResourceColor;
  itemSelectedBackgroundColor: ResourceColor;
  itemBorderRadius: Resource;
}

const multiplyCapsuleTheme: MultiplySegmentButtonV2Theme = {
  itemBorderRadius: $r('sys.float.segment_button_v2_multi_corner_radius'),
  itemBackgroundColor: $r('sys.color.segment_button_v2_multi_capsule_button_background'),
  itemSelectedBackgroundColor: $r('sys.color.comp_background_emphasize'),
  itemSpace: LengthMetrics.vp(1),
  itemFontColor: $r('sys.color.font_secondary'),
  itemSelectedFontColor: $r('sys.color.font_on_primary'),
  itemFontWeight: FontWeight.Medium,
  itemSelectedFontWeight: FontWeight.Medium,
  itemIconFillColor: $r('sys.color.icon_secondary'),
  itemSelectedIconFillColor: $r('sys.color.font_on_primary'),
  itemSymbolFontColor: $r('sys.color.font_secondary'),
  itemSelectedSymbolFontColor: $r('sys.color.font_on_primary'),
  itemFontSize: $r('sys.float.ohos_id_text_size_button2'),
  adaptiveItemFontSize: $r('sys.float.Caption_M'),
  itemIconSize: 24,
  itemSymbolFontSize: 20,
  itemPadding: {
    top: LengthMetrics.resource($r('sys.float.padding_level2')),
    bottom: LengthMetrics.resource($r('sys.float.padding_level2')),
    start: LengthMetrics.resource($r('sys.float.padding_level4')),
    end: LengthMetrics.resource($r('sys.float.padding_level4')),
  },
  itemMinHeight: $r('sys.float.segment_button_v2_multi_singleline_height'),
  hybridItemMinHeight: $r('sys.float.segment_button_v2_multi_doubleline_height'),
  itemMaxFontScale: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleSmallest: SMALLEST_MAX_FONT_SCALE,
  itemMaxFontScaleLargest: LARGEST_MAX_FONT_SCALE,
  itemMinFontScale: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleSmallest: SMALLEST_MIN_FONT_SCALE,
  itemMinFontScaleLargest: LARGEST_MIN_FONT_SCALE,
};

@ComponentV2
export struct MultiCapsuleSegmentButtonV2 {
  @Require
  @Param
  items: SegmentButtonV2Items;
  @Require
  @Param
  selectedIndexes: number[];
  @Event
  $selectedIndexes: OnSelectedIndexesChange;
  @Event
  onItemClicked?: Callback<number>;
  @Param
  itemMinFontScale?: number | Resource = undefined;
  @Param
  itemMaxFontScale?: number | Resource = undefined;
  @Param
  itemSpace?: LengthMetrics = undefined;
  @Param
  itemFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedFontColor?: ColorMetrics = undefined;
  @Param
  itemFontSize?: LengthMetrics = undefined;
  @Param
  itemSelectedFontSize?: LengthMetrics = undefined;
  @Param
  itemFontWeight?: FontWeight = undefined;
  @Param
  itemSelectedFontWeight?: FontWeight = undefined;
  @Param
  itemBorderRadius?: LengthMetrics = undefined;
  @Param
  itemBackgroundColor?: ColorMetrics = undefined;
  @Param
  itemBackgroundEffect?: BackgroundEffectOptions = undefined;
  @Param
  itemBackgroundBlurStyle?: BlurStyle = undefined;
  @Param
  itemBackgroundBlurStyleOptions?: BackgroundBlurStyleOptions = undefined;
  @Param
  itemSelectedBackgroundColor?: ColorMetrics = undefined;
  @Param
  itemIconSize?: SizeT<LengthMetrics> = undefined;
  @Param
  itemIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSelectedIconFillColor?: ColorMetrics = undefined;
  @Param
  itemSymbolFontSize?: LengthMetrics = undefined;
  @Param
  itemSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemSelectedSymbolFontColor?: ColorMetrics = undefined;
  @Param
  itemMinHeight?: LengthMetrics = undefined;
  @Param
  itemPadding?: LocalizedPadding = undefined;
  @Param
  languageDirection?: Direction = undefined;
  private theme: MultiplySegmentButtonV2Theme = multiplyCapsuleTheme;
  private focusGroupId: string = GroupIdGenerator.getInstance().generate();

  build() {
    Flex({ alignItems: ItemAlign.Stretch, space: { main: this.getItemSpace() } }) {
      Repeat(this.getItems())
        .each((repeatItem: RepeatItem<SegmentButtonV2Item>) => {
          Button({ type: ButtonType.Normal }) {
            SegmentButtonV2ItemContent({
              theme: this.theme,
              item: repeatItem.item,
              selected: this.isSelected(repeatItem),
              hasHybrid: this.getItems().hasHybrid,
              itemMinFontScale: this.itemMinFontScale,
              itemMaxFontScale: this.itemMaxFontScale,
              itemFontColor: this.itemFontColor,
              itemSelectedFontColor: this.itemSelectedFontColor,
              itemFontSize: this.itemFontSize,
              itemSelectedFontSize: this.itemSelectedFontSize,
              itemFontWeight: this.itemFontWeight,
              itemSelectedFontWeight: this.itemSelectedFontWeight,
              itemIconSize: this.itemIconSize,
              itemIconFillColor: this.itemIconFillColor,
              itemSelectedIconFillColor: this.itemSelectedIconFillColor,
              itemSymbolFontSize: this.itemSymbolFontSize,
              itemSymbolFontColor: this.itemSymbolFontColor,
              itemSelectedSymbolFontColor: this.itemSelectedSymbolFontColor,
              itemMinHeight: this.itemMinHeight,
              itemPadding: this.itemPadding,
              languageDirection: this.languageDirection,
            })
              .borderRadius(this.getItemButtonBorderRadius(repeatItem))
              .backgroundBlurStyle(this.getItemBackgroundBlurStyle(), this.getItemBackgroundBlurStyleOptions(),
                { disableSystemAdaptation: true })
              .direction(this.languageDirection)
          }
          .accessibilityGroup(true)
          .accessibilityChecked(this.isSelected(repeatItem))
          .accessibilityText(this.getItemAccessibilityText(repeatItem))
          .accessibilityDescription(this.getItemAccessibilityDescription(repeatItem))
          .accessibilityLevel(repeatItem.item.accessibilityLevel)
          .backgroundColor(this.getItemBackgroundColor(repeatItem))
          .backgroundEffect(this.itemBackgroundEffect, { disableSystemAdaptation: true })
          .borderRadius(this.getItemButtonBorderRadius(repeatItem))
          .constraintSize({ minHeight: this.getItemMinHeight() })
          .direction(this.languageDirection)
          .enabled(repeatItem.item.enabled)
          .focusScopePriority(this.focusGroupId, this.getFocusPriority(repeatItem))
          .layoutWeight(1)
          .padding(0)
          .onClick(() => {
            this.onItemClicked?.(repeatItem.index);
            let selection: number[];
            const items = this.getItems();
            const selectedIndexes = this.selectedIndexes ?? [];
            if (this.isSelected(repeatItem)) {
              selection = selectedIndexes.filter((index) => {
                if (index < 0 || index > items.length - 1) {
                  return false;
                }
                return index !== repeatItem.index;
              });
            } else {
              selection = selectedIndexes
                .filter((index) => index >= 0 && index <= items.length - 1)
                .concat(repeatItem.index);
            }
            this.$selectedIndexes(selection);
          })
        })
        .key(generateUniqueKye(this.focusGroupId))
    }
    .clip(false)
    .direction(this.languageDirection)
    .focusScopeId(this.focusGroupId, true)
  }

  private getFocusPriority(repeatItem: RepeatItem<SegmentButtonV2Item>): FocusPriority | undefined {
    const selectedIndexes = this.selectedIndexes ?? [];
    return Math.min(...selectedIndexes) === repeatItem.index ? FocusPriority.PREVIOUS : FocusPriority.AUTO;
  }

  getItems(): SegmentButtonV2Items {
    return this.items ?? EMPTY_ITEMS;
  }

  getItemBackgroundBlurStyleOptions(): BackgroundBlurStyleOptions | undefined {
    if (this.itemBackgroundEffect) {
      return undefined;
    }
    return this.itemBackgroundBlurStyleOptions;
  }

  getItemBackgroundBlurStyle(): BlurStyle | undefined {
    if (this.itemBackgroundEffect) {
      return undefined;
    }
    return this.itemBackgroundBlurStyle;
  }

  private getItemAccessibilityDescription(repeatItem: RepeatItem<SegmentButtonV2Item>): string | undefined {
    return repeatItem.item.accessibilityDescription as ESObject as string;
  }

  private getItemAccessibilityText(repeatItem: RepeatItem<SegmentButtonV2Item>): string | undefined {
    return repeatItem.item.accessibilityText as ESObject as string;
  }

  private getItemSpace(): LengthMetrics {
    if (this.itemSpace && this.itemSpace.unit !== LengthUnit.PERCENT
      && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemSpace)) {
      return this.itemSpace;
    }
    return this.theme.itemSpace;
  }

  private getItemMinHeight(): Length | undefined {
    if (this.itemMinHeight && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemMinHeight)) {
      return LengthMetricsUtils.getInstance().stringify(this.itemMinHeight);
    }
    return this.theme.itemMinHeight;
  }

  private getItemBackgroundColor(repeatItem: RepeatItem<SegmentButtonV2Item>): ResourceColor {
    if (this.isSelected(repeatItem)) {
      return this.itemSelectedBackgroundColor?.color ?? this.theme.itemSelectedBackgroundColor;
    }
    return this.itemBackgroundColor?.color ?? this.theme.itemBackgroundColor;
  }

  private isSelected(repeatItem: RepeatItem<SegmentButtonV2Item>): boolean {
    const selectedIndexes = this.selectedIndexes ?? [];
    return selectedIndexes.includes(repeatItem.index);
  }

  private getItemButtonBorderRadius(repeatItem: RepeatItem<SegmentButtonV2Item>): LocalizedBorderRadiuses {
    const items = this.getItems();
    const noneBorderRadius: LengthMetrics = LengthMetrics.vp(0);
    const borderRadiuses: LocalizedBorderRadiuses = {
      topStart: noneBorderRadius,
      bottomStart: noneBorderRadius,
      topEnd: noneBorderRadius,
      bottomEnd: noneBorderRadius,
    };
    if (repeatItem.index === 0) {
      const borderRadius: LengthMetrics = this.itemBorderRadius ?? LengthMetrics.resource(this.theme.itemBorderRadius);
      borderRadiuses.topStart = borderRadius;
      borderRadiuses.bottomStart = borderRadius;

    }
    if (repeatItem.index === items.length - 1) {
      const borderRadius: LengthMetrics = this.itemBorderRadius ?? LengthMetrics.resource(this.theme.itemBorderRadius);
      borderRadiuses.topEnd = borderRadius;
      borderRadiuses.bottomEnd = borderRadius;
    }
    return borderRadiuses;
  }
}

@ComponentV2
struct SegmentButtonV2ItemContent {
  @Require
  @Param
  hasHybrid: boolean;
  @Require
  @Param
  item: SegmentButtonV2Item;
  @Require
  @Param
  selected: boolean;
  @Require
  @Param
  theme: SegmentButtonV2ContentTheme;
  @Require
  @Param
  itemMinFontScale?: number | Resource = undefined;
  @Require
  @Param
  itemMaxFontScale?: number | Resource = undefined;
  @Require
  @Param
  itemFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemSelectedFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemFontWeight?: FontWeight = undefined;
  @Require
  @Param
  itemSelectedFontWeight?: FontWeight = undefined;
  @Require
  @Param
  itemIconSize?: SizeT<LengthMetrics> = undefined;
  @Require
  @Param
  itemIconFillColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedIconFillColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSymbolFontSize?: LengthMetrics = undefined;
  @Require
  @Param
  itemSymbolFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemSelectedSymbolFontColor?: ColorMetrics = undefined;
  @Require
  @Param
  itemMinHeight?: LengthMetrics = undefined;
  @Require
  @Param
  itemPadding?: LocalizedPadding = undefined;
  @Require
  @Param
  languageDirection?: Direction = undefined;
  @Local useAdaptiveLineHeight: boolean = false;
  private environmentCallbackID?: number = undefined;
  private environmentCallback: EnvironmentCallback = {
    onConfigurationUpdated: (configuration) => {
      this.updateLanguageLineHeight();
    },
    onMemoryLevel() {
    }
  };

  updateLanguageLineHeight(): void {
    const resourceManager = this.getUIContext().getHostContext()?.resourceManager;
    if (!resourceManager) {
      console.error(`[SegmentButtonV2] failed to get resourceManager`);
      return;
    }
    try {
      this.useAdaptiveLineHeight = resourceManager!.getStringByNameSync('text_fallback_line_spacing') === 'true';
    } catch (e) {
      console.error(`[SegmentButtonV2] failed to get text_fallback_line_spacing resource`);
    }
  }

  aboutToAppear(): void {
    if (deviceInfo.sdkApiVersion >= 26) {
      this.updateLanguageLineHeight();
      let abilityContext = this.getUIContext().getHostContext();
      if (abilityContext) {
        this.environmentCallbackID = abilityContext.getApplicationContext().on('environment', this.environmentCallback);
      }
    }
  }

  aboutToDisappear(): void {
    if (deviceInfo.sdkApiVersion >= 26 && this.environmentCallbackID) {
      let abilityContext = this.getUIContext().getHostContext();
      if (abilityContext) {
        abilityContext.getApplicationContext().off('environment', this.environmentCallbackID);
      }
      this.environmentCallbackID = void 0;
    }
  }

  build() {
    Column({ space: 2 }) {
      if (this.item.symbol || this.item.symbolModifier) {
        SymbolGlyph(this.item.symbol)
          .fontSize(this.getSymbolFontSize())
          .fontColor([this.getItemSymbolFillColor()])
          .direction(this.languageDirection)
          .attributeModifier(this.item.symbolModifier)
      } else if (this.item.icon) {
        Image(this.item.icon)
          .fillColor(this.getItemIconFillColor())
          .width(this.getItemIconWidth())
          .height(this.getItemIconHeight())
          .direction(this.languageDirection)
          .draggable(false)
          .attributeModifier(this.item.iconModifier)
      }

      if (this.item.text) {
        Text(this.item.text)
          .direction(this.languageDirection)
          .fontSize(this.getItemFontSize())
          .fontColor(this.getItemFontColor())
          .fontWeight(this.getItemFontWeight())
          .textOverflow({ overflow: TextOverflow.Ellipsis })
          .maxLines(1)
          .maxFontScale(this.getItemMaxFontScale())
          .minFontScale(this.getItemMinFontScale())
          .attributeModifier(this.item.textModifier)
          .includeFontPadding(this.useAdaptiveLineHeight)
          .fallbackLineSpacing(this.useAdaptiveLineHeight)
      }
    }
    .constraintSize({ minHeight: this.getItemMinHeight(), minWidth: '100%' })
    .direction(this.languageDirection)
    .justifyContent(FlexAlign.Center)
    .padding(this.getItemPadding())
  }

  private getItemFontWeight(): string | number | FontWeight {
    if (this.selected) {
      return this.itemSelectedFontWeight ?? this.theme.itemSelectedFontWeight;
    }
    return this.itemFontWeight ?? this.theme.itemFontWeight;
  }

  getItemSymbolFillColor(): ResourceColor {
    if (this.selected) {
      if (this.itemSelectedSymbolFontColor) {
        return this.getColorMetricsResourceColor(this.itemSelectedSymbolFontColor);
      }
      return this.theme.itemSelectedSymbolFontColor;
    }
    if (this.itemSymbolFontColor) {
      return this.getColorMetricsResourceColor(this.itemSymbolFontColor);
    }
    return this.theme.itemSymbolFontColor;
  }

  private getSymbolFontSize(): Dimension {
    if (this.itemSymbolFontSize && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemSymbolFontSize) &&
      this.itemSymbolFontSize.unit !== LengthUnit.PERCENT) {
      return LengthMetricsUtils.getInstance().stringify(this.itemSymbolFontSize);
    }
    return this.theme.itemSymbolFontSize;
  }

  private getItemMaxFontScale() {
    if (typeof this.itemMaxFontScale === 'number') {
      return normalize(this.itemMaxFontScale, this.theme.itemMaxFontScaleSmallest, this.theme.itemMaxFontScaleLargest);
    }
    if (typeof this.itemMaxFontScale === 'object') {
      const itemMaxFontScale: number =
        parseNumericResource(this.getUIContext(), this.itemMaxFontScale) ?? SMALLEST_MAX_FONT_SCALE;
      return normalize(itemMaxFontScale, this.theme.itemMaxFontScaleSmallest, this.theme.itemMaxFontScaleLargest);
    }
    return SMALLEST_MAX_FONT_SCALE;
  }

  private getItemMinFontScale() {
    if (typeof this.itemMinFontScale === 'number') {
      return normalize(this.itemMinFontScale, this.theme.itemMinFontScaleSmallest, this.theme.itemMinFontScaleLargest);
    }
    if (typeof this.itemMinFontScale === 'object') {
      const itemMinFontScale =
        parseNumericResource(this.getUIContext(), this.itemMinFontScale) ?? SMALLEST_MIN_FONT_SCALE;
      return normalize(itemMinFontScale, this.theme.itemMinFontScaleSmallest, this.theme.itemMinFontScaleLargest);
    }
    return SMALLEST_MIN_FONT_SCALE;
  }

  private getItemPadding(): LocalizedPadding | Length | Padding {
    const itemPadding: LocalizedPadding = {
      top: this.theme.itemPadding.top,
      bottom: this.theme.itemPadding.bottom,
      start: this.theme.itemPadding.start,
      end: this.theme.itemPadding.end,
    };

    if (this.itemPadding?.top && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemPadding.top)) {
      itemPadding.top = this.itemPadding.top;
    }

    if (this.itemPadding?.bottom && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemPadding.bottom)) {
      itemPadding.bottom = this.itemPadding.bottom;
    }

    if (this.itemPadding?.start && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemPadding.start)) {
      itemPadding.start = this.itemPadding.start;
    }

    if (this.itemPadding?.end && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemPadding.end)) {
      itemPadding.end = this.itemPadding.end;
    }

    return itemPadding;
  }

  private getItemMinHeight(): Length | undefined {
    if (this.itemMinHeight && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemMinHeight)) {
      return LengthMetricsUtils.getInstance().stringify(this.itemMinHeight);
    }
    return this.hasHybrid ? this.theme.hybridItemMinHeight : this.theme.itemMinHeight;
  }

  private getColorMetricsResourceColor(colorMetrics: ColorMetrics): ResourceColor {
    const resourceId: number = Reflect.get(colorMetrics, 'resourceId_');
    if (typeof resourceId === 'number' && resourceId !== -1) {
      const context: common.Context = this.getUIContext().getHostContext() as common.Context;
      return {
        id: resourceId, type: COLOR_RESOURCE_TYPE,
        bundleName: (context as common.UIAbilityContext)?.abilityInfo?.bundleName ?? '',
        moduleName: (context as common.UIAbilityContext)?.abilityInfo?.moduleName ?? '',
      } as Resource;
    }
    return colorMetrics.color;
  }

  private getItemFontColor(): ResourceColor {
    if (this.selected) {
      if (this.itemSelectedFontColor) {
        return this.getColorMetricsResourceColor(this.itemSelectedFontColor);
      }
      return this.theme.itemSelectedFontColor;
    }
    if (this.itemFontColor) {
      return this.getColorMetricsResourceColor(this.itemFontColor);
    }
    return this.theme.itemFontColor;
  }

  private getItemFontSize(): Length {
    if (this.selected) {
      if (this.itemSelectedFontSize && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemSelectedFontSize) &&
        this.itemSelectedFontSize.unit !== LengthUnit.PERCENT) {
        return LengthMetricsUtils.getInstance().stringify(this.itemSelectedFontSize);
      }
      return this.useAdaptiveLineHeight ? this.theme.adaptiveItemFontSize : this.theme.itemFontSize;
    }
    if (this.itemFontSize && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemFontSize) &&
      this.itemFontSize.unit !== LengthUnit.PERCENT) {
      return LengthMetricsUtils.getInstance().stringify(this.itemFontSize);
    }
    return this.useAdaptiveLineHeight ? this.theme.adaptiveItemFontSize : this.theme.itemFontSize;
  }

  private getItemIconHeight(): Length {
    if (this.itemIconSize?.height && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemIconSize.height)) {
      return LengthMetricsUtils.getInstance().stringify(this.itemIconSize.height);
    }
    return this.theme.itemIconSize;
  }

  private getItemIconWidth(): Length {
    if (this.itemIconSize?.width && LengthMetricsUtils.getInstance().isNaturalNumber(this.itemIconSize.width)) {
      return LengthMetricsUtils.getInstance().stringify(this.itemIconSize.width);
    }
    return this.theme.itemIconSize;
  }

  private getItemIconFillColor(): ResourceColor {
    if (this.selected) {
      if (this.itemSelectedIconFillColor) {
        return this.getColorMetricsResourceColor(this.itemSelectedIconFillColor);
      }
      return this.theme.itemSelectedIconFillColor;
    }
    if (this.itemIconFillColor) {
      return this.getColorMetricsResourceColor(this.itemIconFillColor);
    }
    return this.theme.itemIconFillColor;
  }
}

class LengthMetricsUtils {
  private static instance?: LengthMetricsUtils;

  private constructor() {
  }

  public static getInstance(): LengthMetricsUtils {
    if (!LengthMetricsUtils.instance) {
      LengthMetricsUtils.instance = new LengthMetricsUtils();
    }
    return LengthMetricsUtils.instance;
  }

  stringify(metrics: LengthMetrics): Dimension {
    switch (metrics.unit) {
      case LengthUnit.PX:
        return `${metrics.value}px`;
      case LengthUnit.VP:
        return `${metrics.value}vp`;
      case LengthUnit.FP:
        return `${metrics.value}fp`;
      case LengthUnit.PERCENT:
        return `${metrics.value}%`;
      case LengthUnit.LPX:
        return `${metrics.value}lpx`;
    }
  }

  isNaturalNumber(metrics: LengthMetrics): boolean {
    return metrics.value >= 0;
  }
}

function parseNumericResource(context: UIContext, resource: Resource): number | undefined {
  const resourceManager = context.getHostContext()?.resourceManager;
  if (!resourceManager) {
    return undefined;
  }
  try {
    return resourceManager.getNumber(resource);
  } catch (err) {
    // todo log err
    return undefined;
  }
}

function normalize(value: number, min: number, max: number): number {
  return Math.min(Math.max(value, min), max);
}

function generateUniqueKye(groupId: string) {
  return (item: SegmentButtonV2Item, index: number): string => {
    let key = groupId;
    if (item.text) {
      if (typeof item.text === 'string') {
        key += item.text;
      } else {
        key += getResourceUniqueId(item.text);
      }
    }
    if (item.icon) {
      if (typeof item.icon === 'string') {
        key += item.icon;
      } else {
        key += getResourceUniqueId(item.icon);
      }
    }
    if (item.symbol) {
      key += getResourceUniqueId(item.symbol);
    }
    return key;
  }
}

function getResourceUniqueId(resource: Resource): string {
  if (resource.id !== -1) {
    return `${resource.id}`;
  } else {
    return JSON.stringify(resource);
  }
}

class GroupIdGenerator {
  private static instance: GroupIdGenerator | null = null;
  private id: number = 0;

  private constructor() {
  }

  public static getInstance(): GroupIdGenerator {
    if (!GroupIdGenerator.instance) {
      GroupIdGenerator.instance = new GroupIdGenerator();
    }
    return GroupIdGenerator.instance;
  }

  public generate(): string {
    return util.generateRandomUUID() || `SegmentButton-${this.id++}`;
  }
}