import { AppContentLayoutNav, NavbarType } from '../enums'
import { config } from '@layouts/config'
import { injectionKeyIsVerticalNavHovered } from '@layouts'

export const useLayouts = () => {
  const navbarType = computed({
    get() {
      return config.navbar.type.value
    },
    set(value) {
      config.navbar.type.value = value
    },
  })

  const isNavbarBlurEnabled = computed({
    get() {
      return config.navbar.navbarBlur.value
    },
    set(value) {
      config.navbar.navbarBlur.value = value
      localStorage.setItem(`${config.app.title}-navbarBlur`, value.toString())
    },
  })

  const _setAppDir = dir => {
    document.documentElement.setAttribute('dir', dir)
  }

  const footerType = computed({
    get() {
      return config.footer.type.value
    },
    set(value) {
      config.footer.type.value = value
    },
  })

  const isVerticalNavCollapsed = computed({
    get() {
      return config.verticalNav.isVerticalNavCollapsed.value
    },
    set(val) {
      config.verticalNav.isVerticalNavCollapsed.value = val
      localStorage.setItem(`${config.app.title}-isVerticalNavCollapsed`, val.toString())
    },
  })

  const appContentWidth = computed({
    get() {
      return config.app.contentWidth.value
    },
    set(val) {
      config.app.contentWidth.value = val
      localStorage.setItem(`${config.app.title}-contentWidth`, val.toString())
    },
  })

  const appContentLayoutNav = computed({
    get() {
      return config.app.contentLayoutNav.value
    },
    set(val) {
      config.app.contentLayoutNav.value = val

      // If Navbar type is hidden while switching to horizontal nav => Reset it to sticky
      if (val === AppContentLayoutNav.Horizontal) {
        if (navbarType.value === NavbarType.Hidden)
          navbarType.value = NavbarType.Sticky
        isVerticalNavCollapsed.value = false
      }
    },
  })

  const horizontalNavType = computed({
    get() {
      return config.horizontalNav.type.value
    },
    set(value) {
      config.horizontalNav.type.value = value
    },
  })

  const isLessThanOverlayNavBreakpoint = computed(() => {
    return windowWidth => unref(windowWidth) < config.app.overlayNavFromBreakpoint
  })

  const _layoutClasses = computed(() => (windowWidth, windowScrollY) => {
    const route = useRoute()
    
    return [
      `layout-nav-type-${appContentLayoutNav.value}`,
      `layout-navbar-${navbarType.value}`,
      `layout-footer-${footerType.value}`,
      {
        'layout-vertical-nav-collapsed': isVerticalNavCollapsed.value
                    && appContentLayoutNav.value === 'vertical'
                    && !isLessThanOverlayNavBreakpoint.value(windowWidth),
      },
      { [`horizontal-nav-${horizontalNavType.value}`]: appContentLayoutNav.value === 'horizontal' },
      `layout-content-width-${appContentWidth.value}`,
      { 'layout-overlay-nav': isLessThanOverlayNavBreakpoint.value(windowWidth) },
      { 'window-scrolled': unref(windowScrollY) },
      route.meta.layoutWrapperClasses ? route.meta.layoutWrapperClasses : null,
    ]
  })

  const switchToVerticalNavOnLtOverlayNavBreakpoint = windowWidth => {
    /*
          ℹ️ This is flag will hold nav type need to render when switching between lgAndUp from mdAndDown window width
    
          Requirement: When we nav is set to `horizontal` and we hit the `mdAndDown` breakpoint nav type shall change to `vertical` nav
          Now if we go back to `lgAndUp` breakpoint from `mdAndDown` how we will know which was previous nav type in large device?
    
          Let's assign value of `appContentLayoutNav` as default value of lgAndUpNav. Why 🤔?
            If template is viewed in lgAndUp
              We will assign `appContentLayoutNav` value to `lgAndUpNav` because at this point both constant is same
              Hence, for `lgAndUpNav` it will take value from theme config file
            else
              It will always show vertical nav and if user increase the window width it will fallback to `appContentLayoutNav` value
              But `appContentLayoutNav` will be value set in theme config file
        */
    const lgAndUpNav = ref(appContentLayoutNav.value)


    /*
          There might be case where we manually switch from vertical to horizontal nav and vice versa in `lgAndUp` screen
          So when user comes back from `mdAndDown` to `lgAndUp` we can set updated nav type
          For this we need to update the `lgAndUpNav` value if screen is `lgAndUp`
        */
    watch(appContentLayoutNav, value => {
      if (!isLessThanOverlayNavBreakpoint.value(windowWidth))
        lgAndUpNav.value = value
    })

    /*
          This is layout switching part
          If it's `mdAndDown` => We will use vertical nav no matter what previous nav type was
          Or if it's `lgAndUp` we need to switch back to `lgAndUp` nav type. For this we will tracker property `lgAndUpNav`
        */
    watch(() => isLessThanOverlayNavBreakpoint.value(windowWidth), val => {
      if (!val)
        appContentLayoutNav.value = lgAndUpNav.value
      else
        appContentLayoutNav.value = AppContentLayoutNav.Vertical
    }, { immediate: true })
  }


  /*
      This function will return true if current state is mini. Mini state means vertical nav is:
        - Collapsed
        - Isn't hovered by mouse
        - nav is not less than overlay breakpoint (hence, isn't overlay menu)
  
      ℹ️ We are getting `isVerticalNavHovered` as param instead of via `inject` because
          we are using this in `VerticalNav.vue` component which provide it and I guess because
          same component is providing & injecting we are getting undefined error
    */
  const isVerticalNavMini = (windowWidth, isVerticalNavHovered = null) => {
    const isVerticalNavHoveredLocal = isVerticalNavHovered || inject(injectionKeyIsVerticalNavHovered) || ref(false)
    
    return computed(() => isVerticalNavCollapsed.value && !isVerticalNavHoveredLocal.value && !isLessThanOverlayNavBreakpoint.value(unref(windowWidth)))
  }

  const dynamicI18nProps = computed(() => (key, tag = 'span') => {
    if (config.app.enableI18n) {
      return {
        keypath: key,
        tag,
        scope: 'global',
      }
    }
    
    return {}
  })

  const isAppRtl = computed({
    get() {
      return config.app.isRtl.value
    },
    set(value) {
      config.app.isRtl.value = value
      localStorage.setItem(`${config.app.title}-isRtl`, value.toString())
      _setAppDir(value ? 'rtl' : 'ltr')
    },
  })

  return {
    navbarType,
    isNavbarBlurEnabled,
    footerType,
    isVerticalNavCollapsed,
    appContentWidth,
    appContentLayoutNav,
    horizontalNavType,
    isLessThanOverlayNavBreakpoint,
    _layoutClasses,
    switchToVerticalNavOnLtOverlayNavBreakpoint,
    isVerticalNavMini,
    dynamicI18nProps,
    isAppRtl,
    _setAppDir,
  }
}
