Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/typings / index.base.d.ts
Size: Mime:
/**
 * @see https://martinfowler.com/bliki/DDD_Aggregate.html
 * @see https://vaughnvernon.co/?p=879
 * @see http://www.skuvault.com/blog/defining-creating-skus
 * @see https://www.amazon.com/gp/help/customer/display.html/?nodeId=200779220
 *
 * command + click on react to see  the  CSSProperties - helpful
 */
// import * as ReactTypes from '@types/react'
import { Identifier as ObjectIdentifier } from 'typescript'
import { IComputed } from 'xmobx/mobx'

/**
 * @opinionated <- wip - do not follow yet
 * 1. any properties that are typed as EXCLUSIVELY array | string
 *    that are responded to with an empty value
 *    will be defaulted to an observable.ref(FrozenArray)
 *    OR EMPTY_STRING
 */
// import { EMPTY_ARRAY as FrozenArray } from 'exotic'
import { suggestion } from './typings/@personalization'
import {
  Float,
  NavType,
  onOff,
  LabelValue,
} from './typings/generic'
import { ReviewRating } from './typings/ratings'

type Identifier = string
/**
 * @see https://jira.skava.net/confluence/display/SKC/SE-2038+Product+Personalization
 * @see https://jira.skava.net/confluence/display/SKC/SE-2301+-+3.5.1.3+-+Handle+both+points+and+cash+as+primary+forms+of+payment-Design+Doc
 */
declare namespace personalize {
  /**
   * @name personalizationFlag
   */
  type LabelAsValue = {
    label: 'birthday,wishess' | string,
  }

  type personalization = Array<LabelAsValue>

  // @todo
  // @name personalizationItem
  // like a sku or product 0.0
  //
  // requiredFlag = LabelValue<'required', boolean>
  // 'birthday,wishess'
  //
  // key is the label in the personalize
  // same as with skus
  // type AdditionalInfo_validationData = LabelValue<'validationData', string>
  // additionalinfo = [
  //   { label: 'validationData', value: 'birthday,wishess' },
  // ],
}

/**
 * @invariant
 * 1. the label is always the alt text
 * 2. with no label, there is no alt text
 */
type LabelValueImage = LabelValue<'image'>


/**
 * @see https://jira.skava.net/confluence/display/SKC/ECOMM-2280+-+PIM+-+Subscription+price+for+each+SKU
 */
interface subscription {

}

/**
 * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=16142959
 */
// const StatusCodes = {}

/**
 * @see inStore https://jira.skava.net/confluence/pages/viewpage.action?pageId=10540507
 * @see https://basarat.gitbooks.io/typescript/content/docs/enums.html
 * @see inventory/binitemdetail &skuId=SCLOK5
 */
declare const inStock = 'IN STOCK'
declare const outOfStock = 'OUT OF STOCK'
// NOT REAL YET
declare const inStoreOnly = 'IN STORE ONLY'
declare const onlineOnly = 'IN STORE ONLY'
/**
 * preorder -> available
 * LOW STOCK -> limited stock
 * disable -> SOLD OUT
 */

declare enum InventoryDisplayStatus {
  inStock,
  outOfStock,

  onlineOnly,
  inStoreOnly,
}

/**
 * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=16131393
 */
declare namespace quantity {
  // quantity - item
  // available ?
}

/**
 * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=12701461
 */
declare namespace dynamic {
  // ShippingPolicy
}

type ProductName = string

/**
 * @see https://jira.skava.net/confluence/display/SKC/SE-2038+Product+Personalization
 */
declare namespace identity {
  /**
   * @see mcadmin
   * @name binid
   */
  type binid = Identifier
}



/**
 * @see PIMDefaults https://jira.skava.net/confluence/display/SKC/SE-867+Default+end+date+for+all+entities+in+PIM
 * @see NewArrivals https://jira.skava.net/confluence/pages/viewpage.action?pageId=16141426
 */
declare namespace dates {
  type New_Arrivals = Date
  type preorder = true | false

  /**
   * @invariant
   * 1. the date will either be undefined, or in the format of
   *    @for 2018/09/13 04:17:13
   */
  type preorderdate = string | Date
  type deliverydate = string | Date
}

/**
 * @see ComingSoon https://jira.skava.net/confluence/pages/viewpage.action?pageId=13483697
 */
declare namespace promotions {
  // @see HANW5 - concealed
  type PromoText = 'Limited' | 'Coming Soon' | 'Pre-Order' | 'New' | 'Sold Out'
  type PromoLabel = {
    label: PromoText,
  }

  /**
   * @type {List}
   * @todo don't know how to put together with like `&|`
   *
   * @example 'Limited,Coming Soon ,Pre-Order'
   * @example 'New'
   * @example children.offers[0].properties.iteminfo.description[0].value
   */
  type promomessages = Array<PromoLabel>
}


/**
 * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=12701465
 */
declare namespace visibility {
  type isNotVisible = 'false'
  type isVisible = 'true'
  type Visibility = isVisible | isNotVisible
}

type Visibility = visibility.Visibility

// @example RELBUNDLE / Jio Mega Bundle

interface ProductRelationMetadata {
  /**
   * @invariant
   * 1. groupproduct, iscollection, isbundle will always be computed (on top-level product)
   * 2. these properties only are seen on .iteminfo
   */

  /**
   * @type {MasterProduct} !!
   */
  ismasterproduct?: true | false,

  /**
   * this means the product is part of a collection
   * @see {ProductGroup}
   */
  isgroupproduct?: true | false,
  /**
   * @see {ProductCollection}
   */
  iscollection?: true | false,
  /**
   * @see {ProductBundle}
   */
  isbundle?: true | false,
}


/**
 * @example
 *   label: 'assets'
 *   value: "{"primary":"https://images-na.ssl-images-amazon.com/images/I/61xSGKtZYdL._UY395_.jpg","details":{"Black":"http://d16rliti0tklvn.cloudfront.net/2430/1471675038565.372297198.png"}}"
 *
 * @invariant
 * 1. this will never be used @security
 */
type EvalLabelValueAssets = LabelValue<'assets'>

/**
 * @see #bundle01
 * @see #hanw1
 * @note - used in Collections AND bundles 0.0!?
 * @see pim (likely is the setting "allow bundles in collections")
 */
type GroupIdentifier = LabelValue<'groupId', '' | string>
type SkuSpecification = LabelValue<'' | string, '' | string>

// @todo specifications: - also  similar  to the below
//
// @todo @finish - additionalinfo:
// {
//   label: 'SHIPPING & RETURNS',
//   value:
//     'Product Will Be Replaced With Brand New Product If Any Manufacuring Fault/ Damaged In Transit Is There.',
// },
// {
//   label: 'BUNDLE DESCRIPTION',
//   value:
//     "<p>\nWorld Wear Footwear WORLDWEARFOOTWEAR-347 Casuals (Blue)These pair of Casual Sneakers from the house of Andrew Scott are bound to grab attention. Its sophisticated yet youthful design gives a sense of perfection to your dressing. Pair these sneakers with a Round neck or Polo and a snug fit denim to get that Boyish look.\n</p>\n<b>INCLUDES 3 ITEMS:</b>\n<ul>\n  <li>- World Wear Footwear New-1002 Loafers (Blue)</li>\n  <li>- Navy Canvas Men</li>\n  <li>- Tossido Men's Woven Crew Length Socks (Pack of 4)</li>\n</ul>",
// },

/**
 * @invariant
 * 1. this is optional
 * 2. it will  always be an array
 *
 * @invariant
 * 3. this is only used on top-level .state
 *    OR/AND top level state of any ChildProduct's
 */
type AdditionalInfoList = Array<EvalLabelValueAssets | GroupIdentifier>

interface CategoryItem {
  identifier: Identifier,
  type: 'category',

  /**
   * @enum identifier | ?
   *
   * @opinionated
   * 1. if identifier is used
   *    the link to the product is overridden with our route?
   */
  navtype?: NavType,
}

declare namespace info {
  type CategoryIds = Array<CategoryItem>

  /**
   * @example SSHOM21 <- that product is ghost: true
   *
   * @version ghost1
   * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=13469299
   *
   * @version ghost7
   * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=19474194
   */
  // private interface Flag {}

  /**
   * @example
   *    label: "Description"
   *    value: "Be bold with this Michael Kors Women"
   *
   * @invariant
   * 1. this object may exist as a label without a value
   * 2. if the value is undefined, or falsy,
   *    it will be ignored as no description
   * 3. the description will appear nowhere except .iteminfo
   */
  type Description = LabelValue<'Description'>
  type GhostFlag = LabelValue<'ghost', onOff>

  /**
   * @see https://jira.skava.net/confluence/display/KWS/ProductList+DB+Service
   * @see https://jira.skava.net/confluence/display/SKC/ProductServiceLoad
   *
   * @see https://jira.skava.net/confluence/display/ux/Product?focusedCommentId=18777061#comment-18777061
   *
   * @desc whether this should load subProjects of the product
   *       (bundles, collections) for plp
   *
   * @name shouldLoadSubProducts
   */
  type SubProducts = LabelValue<'subProducts', onOff>
  type Flag = SubProducts | GhostFlag

  /**
   * @name shouldLoadMandatoryProductsForBundleOnCatalog
   */
  type bundleMandatoryProducts = LabelValue<'bundleMandatoryProducts', onOff>

  /**
   * @name shouldLoadOptionalProductsForBundleOnCatalog
   */
  type bundleOptionalProducts = LabelValue<'bundleOptionalProducts', onOff>

  /**
   * @invariant
   * 1. additional options never has ghost
   */
  type AdditionalOptionItem = SubProducts | bundleMandatoryProducts | bundleOptionalProducts

  /**
   * @note - why on earth use this + additional-options
   * @todo @fixme should not support this
   *
   * @invariant
   * 1. value is always dynamic unknown string
   * 2. value is never null
   * 3. there may be multiple flags in additional options
   *
   * @todo !!! forgot whether this was additionalOptions flags - just search
   * ^ need to split up
   */
  type SkuFlagOption = LabelValue<'skuflag'>

  /**
   * |> @important |>
   * @invariant
   * 1. is only used on products that are OnlineOnly / DigitalGoods
   * 2. this means IT NEVER HAS SHIPPING
   *
   * @see #BusinessInternet
   */
  type VirtualFlag = LabelValue<'virtual', boolean>

  /**
   * |> @important |>
   * @todo don't know how we use this
   */
  type bundleMainProduct = LabelValue<'bundleMainProduct', boolean>

  /**
   * @example
   *    label: 'video',
   *    value: 'https://www.youtube.com/watch?v=TSQXjMGgxNc',
   *
   * @invariant
   *    1. value will always be a string, or there
   *    2. there are additional metadata that is ignored
   *       (such as title?) until they are known
   *    3. .videos is always an array of Video
   *
   *    4. .video can occur SIMULTANIOUSLY at top level
   *    5. this is 1:1 with image + additionalImages,
   *       without the clarify for the naming
   */
  type Video = LabelValue<'video', string>

  type FlagList = Array<Flag | SkuFlagOption | VirtualFlag | bundleMainProduct>

  /**
   *
   */
  type AdditionalOptions = Array<AdditionalOptionItem>
  type AdditionalInfoOrOptionsList = AdditionalInfoList | AdditionalOptions
  type VideoList = Array<Video>

  interface ItemInfo extends ProductRelationMetadata {
    flags: FlagList,

    /**
     * @invariant
     * 1. this is optional
     * 2. this can be available on children, or at root, or on skus
     * 3. this is only used currently at the top level
     *
     * @default [] | ?
     */
    categoryids?: CategoryIds,

    /**
     * @default [] | ?
     */
    additionalinfo?: AdditionalInfoOrOptionsList,

    additionalImages: AdditionalImagesList,
    videos?: VideoList,

    /**
     * @default [] | ?
     *
     * @invariant
     * 1. description will only appear here
     */
    description?: Description,
    specifications?: Array<SkuSpecification>
  }
}

/**
 * @alias CategoryIdList
 */
type CategoryIds = info.CategoryIds
type Description = info.Description
type GhostFlag = info.GhostFlag
type Flag = info.Flag
type SubProducts = info.SubProducts
type bundleMandatoryProducts = info.bundleMandatoryProducts
type bundleOptionalProducts = info.bundleOptionalProducts
type bundleMainProduct = info.bundleMainProduct
type SkuFlagOption = info.SkuFlagOption
type AdditionalOptionItem = info.AdditionalOptionItem
type Video = info.Video
type VideoList = info.VideoList
type FlagList = info.FlagList
type AdditionalOptions = info.AdditionalOptions
type AdditionalInfoOrOptionsList = info.AdditionalInfoOrOptionsList
type ItemInfo = info.ItemInfo
type VirtualFlag = info.VirtualFlag

/**
 * @see {Product|Sku|Category} seasional/date configurability
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=19467654
 *
 * @todo - needs clearer finishing
 * @example timings: [{ endtime: '2145916800000' }],
 * @example timings: [{ starttime: '222222000000 }]
 * @example
 *  timings: [{ endtime: '1810980000000', starttime: '1497633234770' }],
 *  starttime: '1495620000000',
 * @todo  ^^^^ WHAT IS THAT
 *
 * @invariant
 * 1. has starttime &| endtime,  or is not  on the state
 *
 */
interface SkuState {
  starttime?: Date | string,
  endtime?: Date | string,
}

/**
 * @todo - use from fixture
 */
type ColorName = string

/**
 * @see Icons/ColorIcon
 *
 * @invariant
 *
 * 1. data layer will not modify this data in any way
 *    one atomic view receive as is
 * 2. a swatch may have both image + name
 * 3. the natural css override of -image vs -color
 *    will delegate responsibility to browser
 *    for rendering the resulting value
 */
interface SwatchType {
  /**
   * set as the background-image
   */
  image?: URL | string,
  /**
   * set as the background-color
   */
  name?: ColorName,
  /**
   * @description this is here (likely) because someone wanted to force bypass
   *              .name being used, to use .image
   *
   * @deprecated
   * @invariant:
   *    1. this will be depreciated
   *    2. after X time, removed
   */
  _name?: ColorName,
}

type SkuColor = SwatchType | ColorName
type SkuColorOrListOfSkuColors = SkuColor | Array<SkuColor>

/**
 * @listens !!!!!!!!!!!!_\_TO_THIS_/_!!!!!!!!!!!!!!!!!!!!
 * @lends this(properties) to Product.skuprops
 *
 * @note - this would mean AndSpecification to match both
 * @name LACE | SHANDW2 | bagcollection
 * @see personalization -> hierarchyfacet
 * @example { color: { name: 'Navy' }, size1: { name: '116 cm' } }
 * @example { color: { name: 'Maroon' }, size1: { name: '114 cm' } }
 *
 * @name  NavyCanvasMen
 * @note - probably is the most complex combination currently available
 * @example {
 *    color: [{image: 'https://www....png', name: 'Ash'}],
 *    size1: [{ name: '10 D' }, { name: '10.5 D' }],
 *
 * @name NESTGUARD
 * @example item.children.skus[0].skuinfo
 *    size1: {name: '6 Pack'}
 * @example product.skuprops
 *   [ {name: '6 Pack'}, {name: '4 Pack'}, {name: 'Single'} ]
 *
 * @example @todo - cannot find example that has the style or fit but they are there o.o
 * @see #mencp1 ^
 * @see https://uxlabs.skavaone.com/skavastream/studio/reader/skava_store/ska_product?navParam=mencp1&
 *
 * @description so you can see,
 *    1. product.skuprops has a list
 *    2. this has the corresponding value to match the value in the list
 *    3. we render the list
 *    4. we click an item
 *    5. we find the sku
 *    6. we set the current sku
 *    7. the current sku has the same data as any other @type Product
 */
interface SkuInfo {
  /**
   * @example 'Pink'
   * @example {name: 'Pink'}
   *
   * @invariant
   * 1. this comes as a string, or array
   * 2. it will always be converted to an array
   * 3. only the first option will be used
   */
  color?: SkuColorOrListOfSkuColors,

  /**
   * @invariant
   * 1. this property is optional
   * 2. when this property exists, it must be an array @throws
   *
   * @todo
   * 1. should not support this at all
   *
   * @example colors?: Array<SkuColor>,
   */

  /**
   * @example 'M'
   * @example [ {name: '6 Pack'}, {name: '4 Pack'}, {name: 'Single'} ]
   *
   * @default ''
   *
   * @invariant
   * 1. size1 is optional
   * 2. size2 is never used @throws
   * 3. every value is either string | object with {name} | array of strings | array of object {name} - with name @throws
   * @todo ^ this invariant is false, it's an array, or string + size
   * @fires !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   */
  size1?: string | Array<Object>,

  /**
   * @invariant
   * 1. this is optional
   * 2. this comes as a string, or array
   * 3. it will always be converted to an array
   * 4. only the first option will be used
   *
   * @invariant
   * 1. api never provides this, only size1
   */
  // size?: Array<string>,

  /**
   * @see mencp1
   */
  style?: string | Array<Object>,

  // may be anything
  // @example `oneDirectory: '1999'
  (x: string): string,
}

interface ProductOptions {
  color?: Array<string>,
  size1?: Array<string>,
  style?: Array<string>,
}

// interface availableOptions {
//   color?: boolean,
//   size?: boolean,
//   fit?: boolean,
// }
// interface selectableOptions {
//   color?: string | Array<string>,
//   size?: string | Array<string>,
//   fit?: string | Array<string>,
// }
// interface selectedOptions {
//   color?: string,
//   size?: string,
//   fit?: string,
// }
interface CurrentlySelectedSkuProps {
  color?: string,
  size1?: string,
  style?: string,
  // may be anything
  // @example `oneDirectory: '1999'
  (x: string): string,
}


interface BaseProductChildren {
  skus?: Array<ProductSku>,

  /**
   * @todo
   * 1. no idea what to use these colors for
   * 2. why are they named .colors on .children o.o
   */
  colors?: SkuColorOrListOfSkuColors,
}

/**
 * @invariant
 * 1. only in cart and checkout
 * 2. cannot accept this mix of data
 */
type InStoreAvailability = { instore: boolean }
type availability = Array<InStoreAvailability>
/**
 * @example '1'
 */
type Status = number


// class ProductCollection {}
// class ProductBundle {}
// class ProductAbstractFactory {}
// class ProductCommon {}

/**
 * @see ELE3 & SELE3
 * @example '1000'
 */
type availablequantity = number
type PreOrder = dates.preorder
type PreOrderDate = dates.preorderdate
type DeliveryDate = dates.deliverydate
type promomessages = promotions.promomessages
type PromoLabel = promotions.PromoLabel
type PromoText = promotions.PromoText

/**
 * @prop buyinfo
 */
interface BuyInfo {
  /**
   * @todo <- have not seen this used in the ui
   */
  availablequantity?: availablequantity,

  promomessages?: promomessages,

  inventorystatus: InventoryDisplayStatus,

  /**
   * @see invariant in the type
   */
  preorder?: PreOrder,

  /**
   * @invariant
   * 1. this will never be on the buyinfo object state
   *    without the accompanying preorder boolean flag
   */
  preorderdate?: PreOrderDate,
  /**
   * sometimes the delivery date is unknown
   * { label: 'skuflag', value: 'iscomingsoon' }
   */
  deliverydate?: DeliveryDate,

  /**
   * @invariant
   * 1. very rare
   * 2. no designs or functionality matched for this scope
   *
   * @note - is related to loyalty
   * @todo whenever they do need it
   */
  personalization?: personalize.personalization,

  /**
   * @invariant
   * 1. is only ever on ViewBag
   */
  instock?: true | false,
}

export type SkuInfoList = Array<SkuInfo>
interface Properties {
  status?: Status
  buyinfo: BuyInfo
  skuinfo: SkuInfo,
  iteminfo: info.ItemInfo,
  state: SkuState,
  reviewrating?: ReviewRating,

  /**
   * @invariant
   * 1. this is found ONLY on the ChildProduct
   * 2. it will be ignored otherwise
   */
  skuprops?: SkuInfoList,

  // iteminfo
  // state:
}

/**
 * @api https://jira.skava.net/confluence/pages/viewpage.action?pageId=12703959
 */
interface StreamPrice {
  /**
   * @invariant
   * 1. a product will always have a price.value from stream @throws
   */
  value: string

  /**
   * @default ''
   */
  label: string

  /**
   * @invariant
   * 1. product will always have price.type as 'Reg' | 'Sale'
   */
  type: 'Reg' | 'Sale'
}

type MainPrimaryImage = string
type AdditionalImagesList = Array<LabelValueImage>

/**
 * @see https://jira.skava.net/confluence/display/SKC/SE-511+-+Asset+Management+in+PIM
 */
interface ProductAssets {
  /**
   * @alias mainImage
   * @alias primaryImage
   *
   * @see productblock
   */
  image: MainPrimaryImage,

  /**
   * @see gallery
   * @alias alternateImages (in PIM)
   *
   * @invariant
   * 1. this is always an Array of 0-*
   * 2. this is ONLY on iteminfo
   */
  additionalimages: AdditionalImagesList,

  /**
   * @alias "colors"
   * @alias "swatchImages"
   *
   * @see ProductOptions View
   * @type {IComputed}
   */
  // swatchImages?: Array<any>,
  // videos
}

/**
 * @type {IComputedValue}
 * @description unite videos + image + additionalimages
 */
interface ProductMediaItem {
  /**
   * @type {Videos}
   */
  isVideo: IComputed,

  /**
   * @type {MainPrimaryImage}
   */
  isPrimaryImage: IComputed,

  /**
   * @type {Image}
   */
  isImage: IComputed,

  /**
   * @alias src
   * @borrows 'value' | 'image'
   */
  value: string,

  /**
   * @alias alt
   * @borrows product.name | image.label
   * @todo MainPrimaryImage has no alt
   * @todo video has no alt
   */
  label: string,
}

interface BaseProductAttributes {
  /**
   * @example /null_image.png
   *
   * @invariant
   * 1. an image is @required to be a valid product @throws
   * 2. when functionality for additional pieces such as color are available
   *    support will be implemented as required
   *
   * 3. the alt text of the .image prop will always be product name
   * @todo ^ this is wrong for SEO
   */
  image: MainPrimaryImage,

  /**
   * @example "Canada Cup, eh"
   *
   * @invariant
   * 1. a name is @required to be a valid product @throws
   * 2. if required, it can default to a description | identifier | image alt
   */
  name: ProductName,

  /**
   * @example "HANDW1"
   * @required
   *
   * @invariant
   * 1. a product will ALWAYS have an identifier
   */
  identifier: Identifier,

  /**
   * @default {BASE_URL}/product/{identifier}
   *
   * @invariant
   * 1. link is optional
   * 2. when provided, it is used in every reference to this product
   *    - plp
   *    - share
   *    - etc
   * 3. when not provided, it will default to our route for it
   */
  link?: URL | string,

  /**
   * @invariant
   * 1. the length of the description
   *    always matches the length of the products
   *    that have descriptions
   *    starting from 0
   *
   * @borrows this.iteminfo.description
   *
   * @requires relations to be done ourselves, client side, for current sku
   */
  description?: string,
  // alternateImages?: Array<any>,


  /**
   * @default product
   * @required
   *
   * @invariant
   * 1. every product has type "product"
   * 2. every children.sku, or any relational data piece that IS A PRODUCT
   *    has type "product"
   * @fires !!!!!!!!!!!!!!Exception!!!!!!!!!!
   * 3. EXCEPTION IS IF USING GHOST: TRUE, TO USE PRODUCT-SKU AS META-DATA/FILTER
   *
   */
  type: 'product' | string,
}

/**
 * @version A
 * @title [SKU sequencing within a product - by facet / by facet value]
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=13488157
 *
 * @see https://jira.skava.net/confluence/display/SKC/Sku+Service
 */
interface ProductSku extends BaseProductAttributes {
  navtype: NavType,
  properties: Properties
}

/**
 * @see https://jira.skava.net/confluence/display/SKC/SE-866+-++Product+grouping+-+Allow+different+products+to+be+shown+in+same+PDP
 */
interface ProductGroup {
  list: Array<ProductGroup>
}

/**
 * @see https://jira.skava.net/confluence/display/SKC/SE-1846+-++%5BAHR%5D+Collection+Product+need+to+load+its+subproducts+sku%27s+in+productlist+call
 */
interface ProductCollection extends BaseProductAttributes {
  /**
   * @type {IComputed}
   * @alias iscomputed
   * @borrows this.iteminfo.iscollection
   */
  isCollection: IComputed,
  // true,
}

/**
 * @see BundleLevelPricing in Cart
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=12704437
 *
 * @see BundleLevelPricing2 in Cart
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=12701469
 *
 * @see BundlesForStoreLocations
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=16142986
 *
 * @api https://jira.skava.net/confluence/display/SKC/Product+Bundle
 * @interface https://jira.skava.net/confluence/display/SKC/PIM+Admin+Item+Helper
 *
 *
 * @example
 * item.children.products === product
 * children.products: [
 *   {
 *     identifier: 'SHOM5',
 *     children: {
 *       //...
 *       skus: [], // <|<-
 *       // ...
 *     }
 *   }
 * ]
 *
 */
interface ProductBundle extends BaseProductAttributes {
  // isbundle

  // true
  isBundle: IComputed | true | false,

  /**
   * @type {IComputed}
   *
   * @borrows this.**.flags[*].bundleMainProduct
   */
  bundleMainProduct: IComputed | true | false,
}


/**
 * @example @see pim & curtab=4&SHOMCOL&isedit=true&step=4
 * @see https://jira.skava.net/confluence/pages/viewpage.action?pageId=16134985
 */
interface ProductBundleItem extends BaseProductAttributes {
  // image: '',
  // identifier: '',
  // name: '',
}


/**
 * @see ViewBag
 * @invariant
 * 1. THE CART IS ONLY A LIST OF SKUS, NOT PRODUCTS
 *
 * @invariant
 * 1. this is only in cartandcheckout
 * 2. @todo @fixme WE CANNOT ACCEPT THIS INSANITY OF PRICE FORMAT
 * @see addtobag.NavyCanvasMen'sClassics
 * @example buyinfo: {
 *   prices: [{ label: 'bundleprice', type: 'PriceInfo', value: '48' }],
 *   additionalinfo: [
 *     { label: 'regPrice', value: '48' },
 *     { label: 'salePrice', value: '48' },
 *   ],
 * }
 *
 * =========
 *
 * @example 1 [
 *    { ismin: 'true', label: 'sale', type: 'Sale', value: '45.0' },
 *    { ismax: 'true', label: 'sale', type: 'Sale', value: '48.0' },
 *    { ismin: 'true', label: 'reg', type: 'Reg', value: '45.0' },
 *    { ismax: 'true', label: 'reg', type: 'Reg', value: '48.0' },
 * ]
 *
 *
 * @example [
 *    { label: 'sale', type: 'Sale', value: '55' },
 *    { label: 'reg', type: 'Reg', value: '65' },
 *  ]
 *
 * ____________________
 * |> Jio Mega Bundle |>
 *
 * @name RELMAINBUN & @prop .bundleMainProduct ->
 * @example [
 *    { ismin: 'true', label: 'sale', type: 'Sale', value: '78.55' },
 *    { ismax: 'true', label: 'sale', type: 'Sale', value: '121.37' },
 * ],
 * @name SRELMAINBUN2 & @prop .ismasterproduct ->
 * @example [
 *    {ismax: 'true', label: 'sale', type: 'Sale', value: '78.55 - 121.37'},
 * ]
 *
 * ______________
 * @name HANW1 > SHANW1
 * @example [
 *   {
 *     ismin: 'true',
 *     label: 'sale',
 *     type: 'Sale',
 *     value: '22-25',
 *   },
 *   {
 *     ismax: 'true',
 *     label: 'sale',
 *     type: 'Sale',
 *     value: '22-25',
 *   },
 *   { label: 'reg', type: 'Reg', value: '28.99' },
 * ],
 */


type PriceList = Array<ProductPrice>

export type CurrencyCode = '$' | string

/**
 * @example SHOMCOL&isedit=true&step=5
 *
 * @see CurrencySign
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=16130098
 *
 * @see VariablePrice
 * @link https://jira.skava.net/confluence/display/SKC/Variable+Price+Product
 *
 * @see VariablePriceAdvanced
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=16140329
 *
 * @see RemoveUpdatePrice
 * @link https://jira.skava.net/confluence/pages/viewpage.action?pageId=16129928
 *
 * @example
 *    ismin: "false",
 *    ismax: "true",
 *    label: "sale",
 *    type: "Sale",
 *    value: "3.99 - 133.0",
 */
interface ProductPrice {
  /**
   * @todo this needs updating - need to make api ticket
   *
   * @invariant
   * 1. the currency will be updated API side to satisfy client requirements
   * 2. the property will not always be provided
   * 3. the first instance it is provided, it will be used thereafter,
   *    until another currency code is found
   *
   */
  currencycode?: CurrencyCode,
  prices: PriceList,
  // salePrice: ''
}

/**
 * @invariant
 * 1. we will accept no product without 1 or more prices @throws
 * 2. money has at sale | reg price
 *
 * 3. money can have an array of prices
 * 4? price list has dates for validity?
 *
 * 5. each item in the array of prices may itself be a range
 * 6. the range can be string,separated, or an [array]
 *
 * 7. when skus have been loaded & are available,
 *    the price list will merge them
 *    ONLY for the summary view
 *    ONLY as a @readonly value
 *
 * 8. if a price list has an object with `ismin`,
 *    that will be preferred
 *    otherwise, it will use the lowest numerical value
 * 9. #8 - same for ismax
 *
 * 10. if the price has 2 or more ranges,
 *    we will ONLY use the highest & the lowest,
 *    while respecting #5 & #6
 *
 *
 * 11. if a price list has only 1 price,
 *    it is never on sale,
 *    and the label defaults to empty
 *
 * 12. in the case where
 *     properties.buyinfo always provides the list of summized prices
 *     from children skus
 *     #7 will be removed
 *
 *
 *
 */
interface Moneys {
  /**
   *
   * @alias regPrice
   * @alias originalPrice
   *
   * @namespace minPrice
   */
  minPrice: ''
}


export type ProductList = Array<OneProductItem>
interface BaseProductChildren {
  skus?: Array<ProductSku>,

  /**
   * @todo
   * 1. no idea what to use these colors for
   * 2. why are they named .colors on .children o.o
   */
  colors?: SkuColorOrListOfSkuColors,

  // @note - probably only on ProductWithPossibleChildren
  // products: ProductList,
}

type ChildrenProductsList = Array<ProductWithPossibleChildren | BarrenProduct>

/**
 * @example .children.products === typeof Array<Products>
 * @alias ProductChildren
 * @alias UnstrictChildren
 * @alias LooseChildren
 * @alias UnknownChildren
 * @alias MaybeProductChildren
 */
interface ProductChildrenWithPossibleGrandChildren {
  products?: ChildrenProductsList,
}

type ProductSkuList = Array<ProductSku>

/**
 * @deprecated
 * @remove
 * @todo @fixme - do not support
 */
interface OverlyComplicatedProductChildren extends BaseProductChildren, ProductChildrenWithPossibleGrandChildren {
  products?: ChildrenProductsList,
  skus?: ProductSkuList,

  /**
   * @todo @fixme ESPECIALLY DO NOT SUPPORT THIS!!!
   */
  colors?: SkuColorOrListOfSkuColors,

  /**
   * @readonly
   * @invariant
   * 1. unused since we don't have this feature working in jquery whitelabel
   */
  suggestion?: ReadonlyArray<any>,

  /**
   * @todo
   * @see #mencp3
   * @see https://uxlabs.skavaone.com/skavastream/studio/reader/skava_store//ska_product?navParam=mencp3&categoryName=Men&plpParam=1474521779826-8
   */
  // relatedproducts: [],
  // recommentedproducts: [],
}

type UnstrictChildren = ProductChildrenWithPossibleGrandChildren
type Children = UnstrictChildren | Array<UnstrictChildren>

/**
 * @alias ParentalProduct
 */
interface ProductWithPossibleChildren {
  children: Children,
}


/**
 * @example
 *
 * @invariant
 * 1. when a product has no children & no children.products, it is barren
 * 2. barren products may be TOP-LEVEL-EMPTY or BOTTOM-LEVEL
 *
 * @alias TopLevelProduct    ~~~
 * @alias BottomLevelProduct ~~~
 */
interface BarrenProduct {
  /**
   * @invariant
   * 1. product will ALWAYS have children
   * 2. children will ALWAYS be an object
   */
  children: BaseProductChildren,
}

type OneProductItem =
  BarrenProduct |
  // ProductChildren |
  ProductBundle |
  ProductCollection

/**
 * @description ANYTHING THAT IS NOT A MANDATORY PRODUCT IS AN ADDON
 */
export type AddOn = OneProductItem
export type AddOnList = Array<AddOn>

export type RelationalProducts = {
  recommentedproducts: ChildrenProductsList,
  relatedproducts: ChildrenProductsList,
}

// order
type ResponseTypeEnum =
  'order'
  | 'orderdetails'
  | 'estimate'
  | 'submitorder'
  // === unrelated
  | 'email'
  // cart
  | 'updatebag'
  | 'viewbag'
  | 'category'
  // list
  | 'createlist-register'
  | 'deleteitem'
  | 'getlistitems'
  | 'getlist'
  | 'getlists'
  | 'additem'
  //
  | 'usertracking'
  | 'getstores'
  // acc
  | 'logout'
  | 'login'
  | 'register'
  // pass
  | 'updatepassword'
  | 'resetpassword'
  // pay
  | 'setpaymentmethod'
  | 'deletecard'
  | 'payment'
  | 'creditcard'
  // ship
  | 'setshippingaddress'
  | 'profile'
  // search
  | 'suggestion'
  // plp pdp
  | 'product'
  | 'catalog'

export {
  MainPrimaryImage,
  AdditionalImagesList,
  LabelValueImage,
  //
  OverlyComplicatedProductChildren,
  AdditionalInfoOrOptionsList,
  ColorName,
  SwatchType,
  Properties,
  ProductGroup,
  ProductAssets,
  BaseProductAttributes,
  SkuColor,
  SkuState,
  SkuInfo,
  ProductOptions,
  InventoryDisplayStatus,
  ProductName,
  PreOrder,
  PreOrderDate,
  PromoText,
  PromoLabel,
  promomessages,
  availablequantity,
  Visibility,
  GroupIdentifier,
  Identifier,
  AdditionalInfoList,

  //
  CategoryItem,
  CategoryItem as CategoryId,
  CategoryIds,
  CategoryIds as CategoryIdList,

  Description,

  GhostFlag,
  SubProducts,
  Flag,
  bundleMandatoryProducts,
  bundleOptionalProducts,
  AdditionalOptionItem,
  SkuFlagOption,
  VirtualFlag,
  bundleMainProduct,
  Video,
  VideoList,
  FlagList,
  ProductRelationMetadata,
  AdditionalOptions,
  ItemInfo,
  BuyInfo,
  PriceList,
  ProductPrice,
  BaseProductChildren,
  OneProductItem,
  BarrenProduct,
  ProductBundle,
  ProductCollection,
  ProductWithPossibleChildren,
  // childrenz
  ChildrenProductsList,
  ProductSkuList,
  ProductSku,
  // availableOptions,
  // selectableOptions,
  CurrentlySelectedSkuProps,
  //
  ResponseTypeEnum,
}
export { ReviewRating }