import { Dispatch, RefObject, SetStateAction } from 'react'

import { BoxProps } from '../box'
import { ButtonProps } from '../button'
import { LinksDict } from '../core'
import { IconProp } from '../icon'
import { ListItemProps, ListProps } from '../list'
import { LogoData } from '../logo/logo.types'
import { MenuProps } from '../menu'
import { SystemProps } from '../system'
import { ThemingProps } from '../theme'
import { HeaderAccountData, HeaderAccountUserInfoData } from './headerAccount.types'

export type HeaderContentProps = BoxProps

export type HeaderContext = Pick<HeaderProps, 'headerHeight'> & {
  isDesktop: boolean
  isMobile: boolean
  isMobileOpen: boolean
  links: LinksDict
  mobileContentRef: RefObject<HTMLElement | null>
  mobileToggleRef: RefObject<HTMLElement | null>
  setIsMobileOpen: Dispatch<SetStateAction<boolean>>
}

export type HeaderCreateAccountData = {
  /** Provides URL to create account link. */
  url?: string
}

export type HeaderCreateAccountProps = BoxProps & HeaderCreateAccountData

export type HeaderLinkData = {
  /** Displays and icon on the left side of the link. */
  icon?: IconProp
  /** Unique name that identifies a link in the links dictionary. */
  id?: string
  /** Adds styling for currently active link. */
  isActive?: boolean
  /** Provides text content to the list item. */
  text?: string
  /** Provides href attribute to the internal link element. */
  url?: string
}

export type HeaderLinkItemProps = ListItemProps & HeaderLinkData

export type HeaderMainLinksProps = ListProps & {
  /** Array of objects with data for each link. */
  links?: HeaderLinkData[]
}

export type HeaderNotificationsData = {
  /** Displays a badge with given number of notifications. */
  count?: number
  /** Provides href to the icon link. */
  url?: string
}

export type HeaderNotificationsProps = ButtonProps & HeaderNotificationsData

export type HeaderProps = SystemProps &
  ThemingProps<'Header'> & {
    /** Sets the height of the Header and is used by internal parts for positioning and sizing. @deprecated; header should always be 72 px.*/
    headerHeight?: number
    isSticky?: boolean
  }

export type HeaderServicesData = {
  /** Array of objects with data for each service link. */
  links?: HeaderLinkData[]
}

export type HeaderServicesProps = MenuProps &
  HeaderServicesData & {
    /** Props object passed to the MenuButton component. */
    buttonProps?: ButtonProps
    /** Children are disabled for this component. */
    children?: never
    isApplication?: boolean
    /** Props object passed to the MenuList component. */
    listProps?: ListProps
    /** Props object passed to the MenuItem component; introduced for app MD */
    showTopBorder?: boolean
  }

export type HeaderSupportProps = MenuProps & HeaderServicesData & {}

export type HeaderButtonData = {
  /** Provides href to the button link. */
  url?: string
}

export type HeaderSignInProps = ButtonProps & HeaderButtonData

export type LoggedInHeaderProps = HeaderProps &
  HeaderButtonData & {
    /** Socket for account popover icon on the right side. */
    account?: HeaderAccountData | JSX.Element
    /** Socket for showing the 'alternative' user Info if showAltUserInfo is enabled */
    altUserInfo?: HeaderAccountUserInfoData
    supportLinks?: HeaderServicesData
    /** Socket for the app name on the left side. */
    applicationName?: string
    applicationUrl?: string
    isApplication?: boolean
    isCleanLayout?: boolean
    isSticky?: boolean
    /** Socket for logo on the left side. */
    logo?: LogoData | JSX.Element
    /** Socket for main links in the middle-right. */
    mainLinks?: HeaderLinkData[] | JSX.Element
    /** Socket for notifications icon on the right side. */
    notifications?: HeaderNotificationsData | JSX.Element
    /** Socket for services menu icon on the right side. */
    services?: HeaderServicesData | JSX.Element
    /** Socket for showing the 'alternative' user Info with role (alternative: 3 lines, role. default: 2 lines, no role); introduced for APP; @default false */
    showAltUserInfo?: boolean
    /** Socket for showing the services trigger up front; introduced for APP; by default it is displayed. */
    showServices?: boolean
    /** Socket for showing the main Links up front in case of APP. by default they are folded into the hamburger menu. */
    showMainLinks?: boolean
  }

export type LoggedOutHeaderProps = HeaderProps & {
  /** Socket for the app name on the left side. */
  applicationName?: string
  applicationUrl?: string
  isApplication?: boolean
  /** Socket for create account prompt on the right side. */
  createAccount?: HeaderCreateAccountData | JSX.Element
  isSticky?: boolean
  /** Socket for logo on the left side. */
  logo?: LogoData | JSX.Element
  /** Socket for links in the middle-right section. */
  mainLinks?: HeaderLinkData[] | JSX.Element
  /** Socket for sign in button on the right side. */
  signIn?: HeaderButtonData | JSX.Element
}
