import { Action, Reducer } from 'redux'
import { AppThunkAction } from '..'
import { ReservedWords } from '../../enumerations'

import { HeaderLink, HeaderModel } from '../../models'

// -----------------
// STATE - This defines the type of data maintained in the Redux store.

export interface HeaderState extends HeaderModel {}

// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects they just describe something that is going to happen.
// Use @typeName and isActionType for type detection that works even after serialization/deserialization.

export interface ReceiveAction extends HeaderModel { type: 'RECEIVE_UPDATE_HEADER' }


// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
// declared type strings (and not any other arbitrary string).
export type KnownAction = ReceiveAction

// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).

export const actionCreators = {

  updateHeader: (props: HeaderModel): AppThunkAction<KnownAction> => (dispatch, getState) => {

    const siteName = getState().content?.siteName
    const baseHeader = getState().content?.header

    const title = (props?.title
      ? props.title
      : baseHeader?.title
        ? baseHeader.title
        : ReservedWords.siteName).replace(ReservedWords.siteName, siteName ? siteName : "")

    // assign default link
    const link = baseHeader?.link
      ? baseHeader.link
      : {}

    // assign default meta
    const meta = baseHeader?.meta
      ? baseHeader.meta
      : {}
      
    // overrid link
    if (props.link)
      Object.keys(props.link).forEach(key => link[key] = props.link[key])

    // override meta
    if(props.meta)
      Object.keys(props.meta).forEach(key => meta[key] = props.meta[key])

    dispatch({ type: 'RECEIVE_UPDATE_HEADER', ...{ title, link, meta } })
  }
}

const unloadedState: HeaderState = {
  title: "",
  link: {},
  meta: {}
}


// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.

export const reducer: Reducer<HeaderState> = (state: HeaderState | undefined, incomingAction: Action): HeaderState => {
  if (state === undefined) {
    return unloadedState
  }

  const action = incomingAction as KnownAction
  switch (action.type) {
    case 'RECEIVE_UPDATE_HEADER':
      return {
        ...action
      }

    default:
      return state
  }
}
