interface Breadcrumb {
  /** Path to node */
  path: string;
  /** Presentation text for node */
  label: string;
}

/** Contains all properties that are used by `NavigationTree` model. */
interface NavigationData<Type extends NavigationItemType, Child> {
  /** Type of node */
  type: Type;
  /** Number of ProductGroups in node */
  count: number;
  /** Child navigation nodes */
  children: Child[];
}
/** Contains all properties that are used by `NavigationTree` model. */
interface NavigationStateData<Type extends NavigationItemType, Child> extends NavigationData<Type, Child> {
  /** Identifies the node as selected in the tree */
  selected: boolean;
  /**
   * Indication that this node has children, even though they might not be present.
   * They might be missing since only one level below a selected node is returned.
   */
  expandable: boolean;
}
/** Contains all properties that are used by `NavigationTree` model. */
interface NavigationProductData {
  /** Path to node */
  path: string;
  /**
   * The path to the image used as this node's icon, if any.
   * @example
   * node.iconPath;
   * > "/resources/images/navigation/spring_node.jpg"
   */
  iconPath?: string;
}
/** Contains properties that are unique to the `'PAGE_LINK'` `type` for `Navigation` and `NavigationTree`. */
interface NavigationLinkData {
  /** Link to page, will only by populated if type is `PAGE_LINK` */
  link: string;
}
/** Contains label property that is common amongst Label, Product and Link nodes */
interface NavigationLabelData {
  /** Presentation text for node */
  label: string;
}

/** Available values for the `type` field for `Navigation` and `NavigationTree` models */
type NavigationItemType = 'PRODUCT' | 'LABEL' | 'PAGE_LINK' | 'SPACER';

type NavigationLabelNode = NavigationData<'LABEL', NavigationNode> & NavigationLabelData;
type NavigationProductNode = NavigationData<'PRODUCT', NavigationNode>
                              & NavigationProductData & NavigationLabelData;
type NavigationLinkNode = NavigationData<'PAGE_LINK', NavigationNode>
                              & NavigationLinkData & NavigationLabelData;
type NavigationSpacerNode = NavigationData<'SPACER', NavigationNode>;

type NavigationLabelStateNode = NavigationStateData<'LABEL', NavigationStateNode>
                                  & NavigationLabelData;
type NavigationProductStateNode = NavigationStateData<'PRODUCT', NavigationStateNode>
                                  & NavigationProductData & NavigationLabelData;
type NavigationLinkStateNode = NavigationStateData<'PAGE_LINK', NavigationStateNode>
                                  & NavigationLinkData & NavigationLabelData;
type NavigationSpacerStateNode = NavigationStateData<'SPACER', NavigationStateNode>;

type NavigationNode = NavigationLabelNode |
                      NavigationProductNode |
                      NavigationLinkNode |
                      NavigationSpacerNode;
type NavigationStateNode = NavigationLabelStateNode |
                           NavigationProductStateNode |
                           NavigationLinkStateNode |
                           NavigationSpacerStateNode;

interface Navigation {
  breadcrumbs: Breadcrumb[];
  tree: NavigationStateNode;
}

export type {
  Breadcrumb, Navigation, NavigationItemType, NavigationNode, NavigationStateNode,
  NavigationLabelNode, NavigationProductNode, NavigationLinkNode, NavigationSpacerNode, NavigationLabelStateNode,
  NavigationProductStateNode, NavigationLinkStateNode, NavigationSpacerStateNode
};
