/*
 * Copyright (c) Huawei Device Co., Ltd. 2024-2025. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import lazy { Dispatch, OhCombinedState, Unsubscribe, getStates, reduxSubscribe } from '../../redux';
import lazy { CommonConstants } from '../../statistics/CommonConstants';
import lazy { ComponentIdKeys } from '../../utils/ComponentIdKeys';
import lazy { PersistType, PreferencesService } from '../../service/preferences/PreferencesService';
import lazy { PublicTag } from '../../service/preferences/PropTag';
import lazy { HiLog } from '../../utils/HiLog';
import lazy { AdaptiveLayoutService, TAB_BAR_HEIGHT } from '../../service/UIAdaptive/AdaptiveLayoutService';
import lazy { DeviceInfo } from '../deviceinfo/DeviceInfo';
import lazy { DisplayService } from '../../service/UIAdaptive/DisplayService';
import lazy { WindowDirection } from '../../utils/WindowDirection';
import lazy { PickerUtils } from '../../utils/PickerUtils';
import lazy { EventBusManager } from '../../worker/eventbus/EventBusManager';
import lazy { EventBus } from '../../worker/eventbus/EventBus';
import lazy { XComponentSize } from '../../utils/types';
import lazy { BaseComponent } from '../../worker/BaseComponent';
import display from '@ohos.display';
import lazy { DirectionCorrectionService } from '../../service/direction/DirectionCorrectionService';
import lazy { PickerWindowType } from './PickerWindowType';
import lazy { PickerAction } from '../../service/picker/PickerAction';
import lazy { FeatureManager } from '../../function/core/FeatureManager';
import lazy { FunctionId } from '../../function/core/functionproperty/FunctionId';
import lazy { SettingFuncDialogItemIndex } from '../settingview/SettingFuncDialogItemIndex';
import lazy { ContextManager } from '../../service/context/ContextManager';
import lazy { LengthMetrics, window } from '@kit.ArkUI';
import lazy { WindowActionType } from '../../redux/actions/WindowActionType';
import lazy { ActionType } from '../../redux/actions/ActionType';
import ResGetter from '../../utils/ResGetter';
import lazy { SystemLanguageUtil } from '../../utils/SystemLanguageUtil';

const TAG: string = 'PrivacyBanner';

const ASPECT_RATIO_4_3 = 4 / 3;

export const DIALOG_OFFSET: number = -240;

const BANNER_BACKGROUND_COLOR: string = '#80000000';
const BANNER_HEIGHT: number = 84;
const BANNER_WIDTH_MAX: number = 400;
const BANNER_HORIZON_WIDTH_MAX: number = 232;
const MARGIN_BANNER_TOP: number = 8;
const MARGIN_BANNER_TOP_HORIZONTAL: number = 12;
const MARGIN_BANNER_TOP_LANDSCAPE: number = 60;
const MARGIN_BANNER_TOP_LANDSCAPE_HORIZONTAL: number = 84;
const MARGIN_BANNER_LEFT_LANDSCAPE_HORIZONTAL: number = 88; //24为百宝箱左边距,48为百宝箱宽度,16为与百宝箱之间的距离。
//tablet
const TABLET_BANNER_TOP: number = 60;
const TABLET_BANNER_TOP_HORIZONTAL = 164;
// pc
const PCTABBAR_HEIGHT: number = 24;
const MARGIN_PCTABBAR_TOP: number = 32;
// GL-B
const G_TOP_FULL: number = -400;
const G_TOP_NO_FULL: number = 70;

const BANNER_ICON_SIZE: number = DeviceInfo.isTv() ? 42 : 32;
const BANNER_PRIVACY_ICON_SIZE: number = DeviceInfo.isTv() ? 24 : 22;
const BANNER_CAMERA_ICON_SIZE: number = DeviceInfo.isTv() ? 18 : 14;
const BORDER_RADIUS_ICON: number = 8;
const BORDER_RADIUS_WIDTH: number = px2vp(1);
const BORDER_RADIUS_ICON_WIDTH: number = px2vp(0.5);
const BORDER_RADIUS_CAMERA_ICON: number = 4;
const BORDER_RADIUS_COLOR: string = '#33808080';
const PRIVACY_ICON_BACKGROUND_COLOR: string = '#e6ffffff';

const MAX_FONT_SCALE: number = 1.3;
const FONT_SIZE_16: Resource = DeviceInfo.isTv() ? $r('sys.float.Caption_L') : $r('sys.float.Body_L');
const FONT_SIZE_14: number = 14;
const FONT_COLOR: string = '#e6ffffff';
const FONT_COLOR_CONTENT: string = '#99ffffff';
const FONT_COLOR_LEARN_MORE: string = '#FF317AF7';
const TEXT_HEIGHT_TITLE: number = 22;
const TEXT_HEIGHT_CONTENT: number = 19;
const TEXT_HEIGHT_CONTENT_SCROLL: number = 38;

const CANCEL_BTN_W: number = 18;
const MARGIN_LEFT_RIGHT: number = 16;
const PADDING_AROUND: number = DeviceInfo.isTv() ? 16 : 12;
const MARGIN_TEXT_LEFT_RIGHT: number = DeviceInfo.isTv() ? 0 : 12;
const BANNER_BORDER_RADIUS: number = 18;

const BANNER_WIDTH_TV: number = 362;

class PickerPrivacyBannerDispatcher {
  private mDispatch: Dispatch = (data) => data;

  public setDispatch(dispatch: Dispatch) {
    this.mDispatch = dispatch;
  }

  public learnMoreSecurityCamera(): void {
    this.mDispatch(PickerAction.learnMoreSecurityCamera());
  }
}

@Extend(Button)
function bannerCancelPartTVTextStyle() {
  .type(ButtonType.Capsule)
  .buttonStyle(ButtonStyleMode.NORMAL)
  .fontColor($r('sys.color.font_primary'))
  .fontSize(18)
  .fontWeight(FontWeight.Regular)
  .maxFontScale(CommonConstants.TEXT_SIZE_HUGE)
  .width(157)
  .height(38)
  .backgroundColor('#1AFFFFFF')
}

@CustomDialog
export struct PrivacyBanner {
  controller: CustomDialogController;
  private mEventBus: EventBus = EventBusManager.getInstance().getEventBus();
  private mBase: BaseComponent = new BaseComponent();
  private mSubscriber: Unsubscribe | null = null;
  private mAction: PickerPrivacyBannerDispatcher = new PickerPrivacyBannerDispatcher();
  private layoutService: AdaptiveLayoutService = AdaptiveLayoutService.getInstance();
  @State previewPosition: number = 0;
  @State windowWidth: number = 0;
  @State windowHeight: number = 0;
  @State xComponentWidth: number = 0;
  @State xComponentHeight: number = 0;
  @State @Watch('onDirectionChange') mDirection: WindowDirection = WindowDirection.TOP;
  @State isShowSemiCollapsed: boolean = false;
  @State isShowLandscape: boolean = false;
  @State isVdeCollapsed: boolean = false;
  @State isHorizontal: boolean = false;
  @State rotateAngle: number = 0;
  @State isRotateLocked: boolean = true;
  @State offsetFullScreen: number = 0;
  @State offsetX: number = 0;
  @State offsetY: number = 0;
  // picker分屏状态
  @State isCollapsedSplitScreen: boolean = !DeviceInfo.isTablet();
  @State isExpandedTopBottomSplitScreen: boolean = PickerUtils.getIsExpandedTopBottomSplitScreen();
  @State isTabletSplitScreen: boolean = PickerUtils.getIsTabletSplitScreen();
  @Link isBannerLoaded: boolean;
  @Link isBannerOpen: boolean;
  @StorageLink('isBannerVisiblePick') isBannerVisiblePick: boolean = false;
  @Link isBannerVisible: boolean;
  @StorageLink('fontSizeScale') fontSizeScale: number = 1;
  @State isFontScaling: boolean = false;
  private displayRotation: number = 0;
  @State bannerHeight: number = 0;
  @StorageProp('isRTL') isRTL: boolean = false;
  @State isShowTricollaps: boolean = false;

  aboutToAppear(): void {
    HiLog.i(TAG, 'Picker privacy banner appears.');
    this.mSubscriber = reduxSubscribe((state: OhCombinedState) => {
      this.isRotateLocked = state.get<boolean>('windowReducer', 'isLockRotation');
      if (this.isSubscriptionNeeded(state.get<WindowDirection>('contextReducer', 'direction'))) {
        this.mDirection =
          DirectionCorrectionService.directionCorrection(state.get<WindowDirection>('contextReducer', 'direction'),
            state.get<boolean>('windowReducer', 'isLockRotation'));
      }
      this.windowWidth = state.get<number>('windowReducer', 'windowWidth');
      this.windowHeight = state.get<number>('windowReducer', 'windowHeight');
      this.xComponentWidth = state.get<number>('previewReducer', 'xComponentWidth');
      this.xComponentHeight = state.get<number>('previewReducer', 'xComponentHeight');
      this.isShowSemiCollapsed = state.get<boolean>('collapsReducer', 'isShowSemiCollapsed');
      this.isShowTricollaps = state.get<boolean>('collapsReducer', 'isShowTricollaps');
      // 因state.get<boolean>('collapsReducer', 'isShowLandscape')更新太慢,导致时序问题,需通过pickerWindowType去判断isShowLandscape
      this.isShowLandscape =
        state.get<PickerWindowType>('windowReducer', 'pickerWindowType') === PickerWindowType.EXPANDED_FULL_SCREEN;
      this.isVdeCollapsed = state.get<boolean>('collapsReducer', 'isVdeCollapsed');
      this.isHorizontal = DisplayService.getInstance().isHorizontal();
    }, (dispatch: Dispatch) => {
      this.mAction.setDispatch(dispatch);
    });
    this.displayRotation = DisplayService.getInstance().getDisplay().rotation;
    this.getOffsetFullScreen();
    this.uxInit();
    this.onDirectionChange();
    this.mEventBus.on(ActionType.ACTION_CHANGE_X_COMPONENT_SIZE,
      (data: XComponentSize) => this.onChangeXComponentSize(), this.mBase.hashCode());
    this.mEventBus.on(WindowActionType.ON_SIZE_CHANGE, () => this.uxInit(), this.mBase.hashCode());
    this.mEventBus.on(WindowActionType.REFRESH_UX, () => this.refreshRotation(), this.mBase.hashCode());
    if (DeviceInfo.isPhone()) {
      this.isBannerVisiblePick = true;
    }
  }

  aboutToDisappear(): void {
    HiLog.i(TAG, 'Picker privacy banner disappears.');
    if (DeviceInfo.isPhone()) {
      this.isBannerVisiblePick = false;
    }
    this.mSubscriber?.destroy();
  }

  private isSubscriptionNeeded(direction: WindowDirection): boolean {
    if (this.isCollapsedSplitScreen) {
      return false;
    }
    const orientation: display.Orientation = DisplayService.getInstance().getDisplay().orientation;
    if (DeviceInfo.isTablet() && this.isRotateLocked &&
      !this.isTabletDirectionSameAxisWithOrientation(direction, orientation)) {
      return false;
    }
    return true;
  }

  private isTabletDirectionSameAxisWithOrientation(direction: WindowDirection,
    orientation: display.Orientation): boolean {
    const verticalAxis: display.Orientation[] = [display.Orientation.PORTRAIT, display.Orientation.PORTRAIT_INVERTED];
    if (verticalAxis.includes(orientation)) {
      return direction === WindowDirection.TOP || direction === WindowDirection.BOTTOM;
    } else {
      return direction === WindowDirection.LEFT || direction === WindowDirection.RIGHT;
    }
  }

  private uxInit(): void {
    const aspectRatio: number = FeatureManager.getInstance().getFunction(FunctionId.ASPECT_RATIO)?.getValue();
    if (!this.isShowLandscape && aspectRatio !== SettingFuncDialogItemIndex.INDEX_SEC) {
      this.layoutService.calLayoutRuleParam(this.windowWidth, this.windowHeight);
      this.layoutService.changePreviewPosition(this.xComponentWidth, this.xComponentHeight);
    }
    this.getOffsetFullScreen();
    this.updateOffsetXY();
    this.isCollapsedSplitScreen = !DeviceInfo.isTablet();
    this.isExpandedTopBottomSplitScreen = PickerUtils.getIsExpandedTopBottomSplitScreenFromReducer();
    this.isTabletSplitScreen = PickerUtils.getIsTabletSplitScreen();
  }

  private refreshRotation(): void {
    this.displayRotation = DisplayService.getInstance().getDisplay().rotation;
    this.onDirectionChange();
  }

  private onDirectionChange(): void {
    this.updateOffsetXY();
    const isUIExtensionPicker: boolean =
      PickerUtils.getIsPicker() && !!ContextManager.getInstance().getUiExtensionContext();
    HiLog.i(TAG, 'isUIExtensionPicker: ' + isUIExtensionPicker);
    if (isUIExtensionPicker) {
      if (this.displayRotation === 0) {
        this.rotateAngle = getStates().get<number>('contextReducer', 'rotateAngle');
      } else {
        this.rotateAngle = 0;
      }
    } else {
      this.rotateAngle = getStates().get<number>('contextReducer', 'rotateAngle');
    }
    if (this.isRotateLocked) {
      if (DeviceInfo.isTablet() && !PickerUtils.getIsTabletFullScreenFromReducer()) {
        this.rotateAngle = 0;
        return;
      }
      if (PickerUtils.getIsExpandedTopBottomSplitScreenFromReducer()) {
        this.rotateAngle -= 90;
      }
    }
  }

  private updateOffsetXY(): void {
    this.offsetX = this.getBannerOffsetX();
    this.offsetY = this.getBannerOffsetY();
  }

  private onChangeXComponentSize(): void {
    setTimeout(() => {
      // 时序问题,刷新XComponentSize大小,预览区位置等配置还未刷新,picker就获取,导致获取的不对,设置延时,使配置刷新之后再去获取
      this.getOffsetFullScreen();
      this.bannerTranslateAnimation();
    }, 100);
  }

  private bannerTranslateAnimation(): void {
    animateTo({ curve: Curve.Sharp, duration: 250 }, () => {
      this.updateOffsetXY();
    });
  }

  private closeBannerButton(): void {
    HiLog.i(TAG, 'The privacy banner has been closed.');
    this.isBannerLoaded = true;
    PreferencesService.getInstance()
      .putPublicValue(PersistType.FOREVER, PublicTag.PICKER_IS_BANNER_LOADED, this.isBannerLoaded);
    AppStorage.setOrCreate('isBannerLoaded', true);
    HiLog.i(TAG, `isBannerLoaded was stored as: ${this.isBannerLoaded}`);
    this.isBannerOpen = false;
    this.controller.close();
  }

  private isVertical(): boolean {
    return this.mDirection === WindowDirection.TOP || this.mDirection === WindowDirection.BOTTOM;
  }

  private getBannerWidth(): number {
    if (DeviceInfo.isTv()) {
      return BANNER_WIDTH_TV;
    }
    if (this.isCollapsedSplitScreen) {
      return this.windowWidth - 2 * MARGIN_LEFT_RIGHT;
    }
    let bannerWidth: number = this.isShowSemiCollapsed ? this.xComponentHeight - 2 * MARGIN_LEFT_RIGHT :
      this.xComponentWidth - 2 * MARGIN_LEFT_RIGHT;
    if (PickerUtils.getIsTabletLeftRightSplitScreenFromReducer()) {
      return 360;
    }
    if (this.isVertical() || this.isShowLandscape) {
      return Math.min(BANNER_WIDTH_MAX, bannerWidth);
    } else {
      return Math.min(BANNER_HORIZON_WIDTH_MAX, bannerWidth);
    }
  }

  private getBannerOffsetX(): number {
    let coefficient: number = this.mDirection === WindowDirection.LEFT && !this.isVdeCollapsed ? -1 : 1;
    if (this.isExpandedTopBottomSplitScreen) {
      let prevPos: number = this.layoutService.previewPosition;
      let compHeight: number = this.xComponentHeight;
      if (this.layoutService.previewPosition === 0) {
        prevPos = this.layoutService.previewPosition4to3;
        compHeight = this.layoutService.preview4to3Height;
      }
      if (!this.isVertical()) {
        return prevPos + compHeight / 2 - this.windowHeight / 2;
      } else {
        return prevPos + 6 - this.windowHeight / 2 + BANNER_HEIGHT / 2;
      }
    }
    if (this.isTabletSplitScreen) {
      return 0;
    }
    if (DeviceInfo.isPc()) {
      return 0;
    } else if (DeviceInfo.isTablet()) {
      return 0;
    } else if (this.isHorizontal) {
      if (this.isShowLandscape && !this.isShowSemiCollapsed && this.isRotateLocked) {
        if (this.isVertical()) {
          return 0;
        }
        return (-1 / 2 * this.xComponentHeight + 45);
      }
      return this.isRotateLocked && this.isVertical() ?
        (-1 / 2 * this.xComponentHeight + 30) * coefficient : 0;
    } else {
      if (this.isShowTricollaps && !this.isVertical()) {
        const offset = -1 / 2 * (this.xComponentWidth - this.bannerHeight) + MARGIN_BANNER_LEFT_LANDSCAPE_HORIZONTAL;
        return offset < G_TOP_FULL ? offset : offset - G_TOP_NO_FULL;
      }
      let offset =
        this.isShowLandscape ? -1 / 2 * this.windowHeight + MARGIN_BANNER_LEFT_LANDSCAPE_HORIZONTAL + BANNER_HEIGHT :
          (1 / 2 * this.windowWidth - MARGIN_BANNER_TOP_HORIZONTAL - 1 / 2 * this.bannerHeight) * coefficient;
      return this.isShowSemiCollapsed ? BANNER_HEIGHT : !this.isVertical() ? offset : 0;
    }
  }

  private getBannerOffsetY(): number {
    if (this.isExpandedTopBottomSplitScreen) {
      const offsetLeftDirection: number = this.windowWidth - BANNER_HEIGHT - MARGIN_BANNER_TOP_HORIZONTAL;
      const offsetRightDirection: number = MARGIN_BANNER_TOP_HORIZONTAL;
      const offsetTopDirection: number =
        this.windowWidth - (BANNER_HEIGHT / 2 + this.getBannerWidth() / 2) - MARGIN_LEFT_RIGHT;
      const resultArr: number[] = [offsetLeftDirection, offsetRightDirection, offsetTopDirection, offsetTopDirection];
      return resultArr[this.mDirection];
    }
    if (this.isCollapsedSplitScreen) {
      return PickerUtils.currentTabBarPosition + TAB_BAR_HEIGHT + 8;
    }
    if (DeviceInfo.isTablet()) {
      return this.getTabletBannerOffsetY();
    } else if (DeviceInfo.isPc()) {
      let offset =
        ((this.windowHeight - this.xComponentHeight) >= 0) ? (this.windowHeight - this.xComponentHeight) / 2 : 0;
      return offset - PCTABBAR_HEIGHT;
    } else if (this.isShowSemiCollapsed) {
      return 1 / 2 * this.windowHeight - BANNER_ICON_SIZE - PADDING_AROUND + 2;
    } else {
      return this.getBannerPhoneOffsetY();
    }
  }

  private getTabletBannerOffsetY(): number {
    if (this.isTabletSplitScreen) {
      return 50;
    }
    if (DisplayService.getInstance().isOrientationVertical()) {
      const previewPosition4to3: number = (this.windowHeight - this.windowWidth * 4 / 3) / 2;
      const previewPosition1to1: number = (this.windowHeight - this.windowWidth) / 2;
      const offset: number = previewPosition4to3 + (previewPosition1to1 - previewPosition4to3 - BANNER_HEIGHT) / 2;
      return this.mDirection === WindowDirection.TOP ? offset : this.windowHeight - offset - BANNER_HEIGHT;
    } else {
      return this.mDirection === WindowDirection.TOP ? TABLET_BANNER_TOP :
        this.windowHeight - TABLET_BANNER_TOP - BANNER_HEIGHT;
    }
  }

  private getOffsetFullScreen(): void {
    const previewPosition4to3: number = this.layoutService.previewPosition4to3;
    this.previewPosition = this.isShowTricollaps ? 90 : this.layoutService.previewPosition;
    const isFullRatio = this.previewPosition === 0;
    this.offsetFullScreen = (isFullRatio && !this.isShowTricollaps) ? previewPosition4to3 : 0;
  }

  private getBannerPhoneOffsetY(): number {
    if (this.isHorizontal) {
      if (this.isShowLandscape && !this.isShowSemiCollapsed && this.isRotateLocked) {
        if (this.isVertical()) {
          return MARGIN_BANNER_TOP_LANDSCAPE_HORIZONTAL;
        }
        return 1 / 2 * this.xComponentHeight;
      }
      return this.isRotateLocked && this.isVertical() ?
        1 / 2 * this.xComponentWidth - MARGIN_BANNER_LEFT_LANDSCAPE_HORIZONTAL : MARGIN_BANNER_TOP_LANDSCAPE_HORIZONTAL;
    }
    if (this.isVertical()) {
      return this.isShowLandscape ? MARGIN_BANNER_TOP_LANDSCAPE :
        this.previewPosition + MARGIN_BANNER_TOP + this.offsetFullScreen;
    }
    if (this.isShowTricollaps) {
      return (1 / 2 * (this.xComponentHeight - this.getBannerWidth()) +
        1 / 2 * (this.getBannerWidth() - this.bannerHeight));
    }
    let previewPosition1to1Center =
      this.layoutService.previewPosition1to1 + 1 / 2 * (this.getBannerWidth() - this.bannerHeight) +
        1 / 2 * (this.xComponentWidth - this.getBannerWidth());
    if (getStates().get<window.WindowStatusType>('windowReducer', 'windowStatus') ===
      window.WindowStatusType.FLOATING) {
      previewPosition1to1Center -= 62;
    }
    return this.isShowLandscape ? 1 / 2 * this.xComponentHeight - 30 : previewPosition1to1Center;
  }

  private getBannerTextContentWidth(): number {
    if (DeviceInfo.isTv()) {
      return 272;
    } else {
      return this.getBannerWidth() - BANNER_ICON_SIZE - PADDING_AROUND - 2 * MARGIN_TEXT_LEFT_RIGHT;
    }
  }

  private isMinorityLanguage(): boolean { //法语|越南语|西班牙语|藏语
    return SystemLanguageUtil.French() || SystemLanguageUtil.isSpanish() || SystemLanguageUtil.isVietnamese() ||
    SystemLanguageUtil.isTibetan()
  }

  @Builder
  BannerIconPart() {
    Stack() {
      Rect({ width: BANNER_ICON_SIZE, height: BANNER_ICON_SIZE, radius: BORDER_RADIUS_ICON })
        .fill(PRIVACY_ICON_BACKGROUND_COLOR)
        .borderRadius({
          topLeft: BORDER_RADIUS_ICON,
          topRight: BORDER_RADIUS_ICON,
          bottomLeft: BORDER_RADIUS_ICON,
          bottomRight: BORDER_RADIUS_CAMERA_ICON
        })
        .borderWidth(BORDER_RADIUS_WIDTH)
        .borderColor(BORDER_RADIUS_COLOR)
      Image($r('app.media.ic_public_privacy'))
        .width(BANNER_PRIVACY_ICON_SIZE)
        .height(BANNER_PRIVACY_ICON_SIZE)
        .draggable(false)
        .alignSelf(ItemAlign.Center)
        .align(Alignment.Center)

      Image($r('app.media.foreground_icon_phone'))
        .borderRadius(BORDER_RADIUS_CAMERA_ICON)
        .borderWidth(BORDER_RADIUS_ICON_WIDTH)
        .borderColor(BORDER_RADIUS_COLOR)
        .width(BANNER_CAMERA_ICON_SIZE)
        .height(BANNER_CAMERA_ICON_SIZE)
        .margin({
          left: BANNER_ICON_SIZE - BANNER_CAMERA_ICON_SIZE - 2 * BORDER_RADIUS_WIDTH + 2 * BORDER_RADIUS_ICON_WIDTH,
          top: BANNER_ICON_SIZE - BANNER_CAMERA_ICON_SIZE - 2 * BORDER_RADIUS_WIDTH + 2 * BORDER_RADIUS_ICON_WIDTH
        })
        .draggable(false)
    }
    .margin(DeviceInfo.isTv() ? { end: LengthMetrics.vp(16) } : undefined)
    .id('banner_icon')
  }

  @Builder
  BannerTextPart() {
    Column() {
      Row() {
        Text($r('app.string.picker_security_camera_popup_title'))
          .size({
            width: DeviceInfo.isTv() ? this.getBannerTextContentWidth() :
              this.getBannerTextContentWidth() - CANCEL_BTN_W
          })
          .height(DeviceInfo.isTv() ? 24 : undefined)
          .fontSize(DeviceInfo.isTv() ? 18 : FONT_SIZE_16)
          .lineHeight(TEXT_HEIGHT_TITLE)
          .maxFontScale(MAX_FONT_SCALE)
          .maxLines(2)
          .textOverflow({
            overflow: TextOverflow.Ellipsis
          })
          .fontColor(FONT_COLOR)
          .textAlign(TextAlign.Start)
          .fontWeight(FontWeight.Medium)
          .id('banner_title')
        if (!DeviceInfo.isTv()) {
          this.BannerCancelPart();
        }
      }
      .alignItems(VerticalAlign.Top)
      .justifyContent(DeviceInfo.isTv() ? FlexAlign.Start : FlexAlign.SpaceBetween)

      if (this.isMinorityLanguage()) {
        Text() {
          Span($r('app.string.picker_security_camera_banner_content', ''))
            .fontColor(DeviceInfo.isTv() ? FONT_COLOR_CONTENT : FONT_COLOR)
        }
        .accessibilityNextFocusId('focusExposureArea')
        .wordBreak(DeviceInfo.isTv() ? WordBreak.BREAK_ALL : undefined)
        .lineHeight(this.fontSizeScale)
        .size({ width: this.getBannerTextContentWidth() })
        .margin(DeviceInfo.isTv() ? { top: 4 } : undefined)
        .fontSize(DeviceInfo.isTv() ? FONT_SIZE_16 : FONT_SIZE_14)
        .fontWeight(FontWeight.Regular)
        .lineHeight(TEXT_HEIGHT_CONTENT)
        .maxFontScale(MAX_FONT_SCALE)
        .id('banner_content')
        .height(this.isVdeCollapsed ? 62 : (DeviceInfo.isTv() ? 42 : ''))

        if (!DeviceInfo.isTv()) {
          Row() {
            Text() {
              Span($r('app.string.picker_security_camera_banner_learn_more'))
                .fontColor(FONT_COLOR_LEARN_MORE)
                .onClick(() => {
                  this.mAction.learnMoreSecurityCamera();
                })
            }
            .accessibilityNextFocusId('focusExposureArea')
            .wordBreak(DeviceInfo.isTv() ? WordBreak.BREAK_ALL : undefined)
            .lineHeight(this.fontSizeScale)
            .size({ width: this.getBannerTextContentWidth() })
            .margin(DeviceInfo.isTv() ? { top: 4 } : undefined)
            .fontSize(DeviceInfo.isTv() ? FONT_SIZE_16 : FONT_SIZE_14)
            .fontWeight(FontWeight.Regular)
            .lineHeight(TEXT_HEIGHT_CONTENT)
            .maxFontScale(MAX_FONT_SCALE)
            .id('banner_content')
            .height(this.isVdeCollapsed ? 62 : (DeviceInfo.isTv() ? 42 : ''))
          }.visibility(Visibility.None)
        }
      } else {
        Text() {
          Span($r('app.string.picker_security_camera_banner_content', ''))
            .fontColor(DeviceInfo.isTv() ? FONT_COLOR_CONTENT : FONT_COLOR)
          if (!DeviceInfo.isTv()) {
            Span($r('app.string.picker_security_camera_banner_learn_more'))
              .fontColor(FONT_COLOR_LEARN_MORE)
              .onClick(() => {
                this.mAction.learnMoreSecurityCamera();
              }).visibility(Visibility.None)
          }
        }
        .accessibilityNextFocusId('focusExposureArea')
        .wordBreak(DeviceInfo.isTv() ? WordBreak.BREAK_ALL : undefined)
        .lineHeight(this.fontSizeScale)
        .size({ width: this.getBannerTextContentWidth() })
        .margin(DeviceInfo.isTv() ? { top: 4 } : undefined)
        .fontSize(DeviceInfo.isTv() ? FONT_SIZE_16 : FONT_SIZE_14)
        .fontWeight(FontWeight.Regular)
        .lineHeight(TEXT_HEIGHT_CONTENT)
        .maxFontScale(MAX_FONT_SCALE)
        .id('banner_content')
        .height(this.isVdeCollapsed ? 62 : (DeviceInfo.isTv() ? 42 : ''))
      }
    }
  }

  @Builder
  BannerCancelPart() {
    Button() {
      Image($r('app.media.ic_camera_cancel_w'))
        .width(CANCEL_BTN_W)
        .fillColor(Color.White)
        .draggable(false)
        .syncLoad(true)
    }
    .type(ButtonType.Normal)
    .backgroundColor(Color.Transparent)
    .key(ComponentIdKeys.PICKER_PRIVACY_BANNER_BUTTON)
    .onClick(() => {
      this.closeBannerButton();
    })
  }

  @Builder
  BannerCancelPartTV() {
    Row({ space: 16 }) {
      Button($r('app.string.light_painting_help_no_more'))
        .onClick(() => {
          this.closeBannerButton();
        })
        .bannerCancelPartTVTextStyle()
      Button($r('app.string.distributed_mode_learn_more'))
        .onClick(() => {
          this.mAction.learnMoreSecurityCamera();
        })
        .bannerCancelPartTVTextStyle()
    }
    .margin({ top: 16 })
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Center)
    .width('100%')
  }

  build() {
    Column() {
      Row() {
        this.BannerIconPart();
        Row() {
          this.BannerTextPart();
        }
        .alignItems(VerticalAlign.Top)
        .margin({ left: MARGIN_TEXT_LEFT_RIGHT, right: MARGIN_TEXT_LEFT_RIGHT })
      }
      .alignItems(VerticalAlign.Top)
      .width('100%')

      if (DeviceInfo.isTv()) {
        this.BannerCancelPartTV()
      }
    }
    .padding(PADDING_AROUND)
    .backgroundColor(DeviceInfo.isTv() ? undefined : BANNER_BACKGROUND_COLOR)
    .backgroundBlurStyle(DeviceInfo.isTv() ? BlurStyle.COMPONENT_THIN : undefined)
    .clip(true)
    .offset(this.getOffSet())
    .width(this.getBannerWidth())
    .border(DeviceInfo.isTv() ? { width: 1, color: '#26FFFFFF' } : undefined)
    .borderRadius(DeviceInfo.isPc() ? $r('sys.float.corner_radius_level4') : $r('sys.float.corner_radius_level10'))
    .shadow(DeviceInfo.isTv() ? ShadowStyle.OUTER_DEFAULT_MD : undefined)
    .rotate({ angle: this.isShowSemiCollapsed ? 90 : this.isVdeCollapsed || DeviceInfo.isPc() ? 0 : this.rotateAngle })
    .key(ComponentIdKeys.PICKER_PRIVACY_BANNER)
    .visibility(this.isBannerVisible ? Visibility.Visible : Visibility.None)
    .onAreaChange((oldValue: Area, newValue: Area) => {
      HiLog.i(TAG,
        `area new width:${newValue?.width},height:${newValue?.height},isBannerVisible:${this.isBannerVisible}`);
      if (!this.isBannerVisible) {
        return;
      }
      this.bannerHeight = parseFloat(newValue?.height?.toString()) ?? BANNER_HEIGHT;
      this.updateOffsetXY();
    })
  }

  private getOffSet(): Position {
    if (DeviceInfo.isTv()) {
      return this.isRTL ? { x: -403, y: 22 } : { x: 403, y: 22 };
    }
    if (this.isVdeCollapsed) {
      const isLockOrientation: boolean = getStates().get<boolean>('windowReducer', 'isLockRotation'); //锁定方向
      if (isLockOrientation) {
        return { x: this.offsetX - 56, y: this.offsetY - DIALOG_OFFSET + 40 };
      }
      switch (this.mDirection) {
        case WindowDirection.TOP:
          return { x: this.offsetX, y: this.offsetY - DIALOG_OFFSET + 40 };
        case WindowDirection.RIGHT:
          return { x: this.offsetX - 56, y: this.offsetY - DIALOG_OFFSET + 40 };
        case WindowDirection.LEFT:
          return { x: this.offsetX + 56, y: this.offsetY - DIALOG_OFFSET + 40 };
        default:
          return { x: this.offsetX - 56, y: this.offsetY - DIALOG_OFFSET + 40 };
      }
    }
    if (DeviceInfo.isPc() || (DeviceInfo.isTablet() && PickerUtils.getIsInPcMode())) {
      // PC和自由多窗下CustomDialog 组件无法偏移出窗口
      return {
        x: this.offsetX,
        y: this.offsetY
      }
    }
    return {
      x: this.offsetX,
      y: this.offsetY - DIALOG_OFFSET
    };
  }
}