import { $ecomConfig, randomObjectId } from '@ecomplus/utils'
import * as EventEmitter from 'eventemitter3'
import addItem from './methods/add-item'
import addPoduct from './methods/add-product'
import fixItem from './methods/fix-item'
import increaseItemQnt from './methods/increase-item-qnt'
import parseProduct from './methods/parse-product'
import removeItem from './methods/remove-item'
import save from './methods/save'
import clear from './methods/clear'
import reset from './methods/reset'
const defaultStorage = typeof window === 'object' && window.localStorage
/**
* Construct a new shopping cart instance object.
* @constructor
* @param {number} [storeId=$ecomConfig.get('store_id')] - Preset Store ID number
* @param {string|null} [storageKey] - Item key to persist cart data
* @param {object} [localStorage=window.localStorage] -
* [Local Storage interface]{@link https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage}
*
* @example
// Default instance
const ecomCart = new EcomCart()
* @example
// Defining Store ID other than the configured on `$ecomConfig`
const storeId = 2000
const customEcomCart = new EcomCart(storeId)
*/
const EcomCart = function (storeId, storageKey = 'ecomShoppingCart', localStorage = defaultStorage) {
const ecomCart = this
/**
* Construct a new shopping cart instance object.
* @memberof EcomCart
* @type {function}
* @see EcomCart
*/
ecomCart.Constructor = EcomCart
/**
* Respective Store ID number.
* @memberof EcomCart
* @type {number}
*/
ecomCart.storeId = storeId || $ecomConfig.get('store_id')
/**
* Item key to handle persistent JSON {@link EcomCart#data}
* with [localStorage]{@link EcomCart#localStorage}.
* @memberof EcomCart
* @type {string|null}
*/
ecomCart.storageKey = storageKey
/**
* [Storage interface]{@link https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage}.
* @memberof EcomCart
* @type {object}
*/
ecomCart.localStorage = localStorage
/**
* Shopping cart data following
* {@link https://developers.e-com.plus/docs/api/#/store/carts/carts E-Com Plus cart object model}.
* @memberof EcomCart
* @type {object}
* @property {string} _id - Cart object ID
* @property {array<object>} items - List of cart items
* @property {number} subtotal - Cart subtotal value
*/
ecomCart.data = {
items: [],
subtotal: 0
}
const emitter = new EventEmitter()
;['on', 'off', 'once'].forEach(method => {
ecomCart[method] = (ev, fn) => {
emitter[method](ev, fn)
}
})
const methodsMiddleware = (method, args = [], emitChange = true) => {
const result = method(ecomCart, emitter, args)
if (result && emitChange) {
const { data } = ecomCart
/**
* @event EcomCart#change
* @type {object}
* @property {object} data - Shopping cart data
* @example ecomCart.on('change', ({ data }) => { console.log(data.items) })
*/
emitter.emit('change', { data })
}
return result
}
this.addItem = (newItem, canSave) => {
return methodsMiddleware(addItem, [newItem, canSave])
}
this.addProduct = (product, variationId, quantity, canSave) => {
return methodsMiddleware(addPoduct, [product, variationId, quantity, canSave])
}
this.fixItem = (item, canSave) => {
return methodsMiddleware(fixItem, [item, canSave])
}
this.increaseItemQnt = (itemId, quantity, canSave) => {
return methodsMiddleware(increaseItemQnt, [itemId, quantity, canSave])
}
this.parseProduct = (product, variationId, quantity) => {
return methodsMiddleware(parseProduct, [product, variationId, quantity], false)
}
this.removeItem = (itemId, canSave) => {
return methodsMiddleware(removeItem, [itemId, canSave])
}
this.clear = (canSave) => {
return methodsMiddleware(clear, [canSave])
}
this.reset = (canSave) => {
return methodsMiddleware(reset, [canSave])
}
this.save = (canFixSubtotal) => {
return methodsMiddleware(save, [canFixSubtotal], false)
}
if (localStorage && storageKey) {
const json = localStorage.getItem(storageKey)
if (json) {
let data
try {
data = JSON.parse(json)
} catch (e) {
// ignore invalid JSON
}
if (data && Array.isArray(data.items)) {
ecomCart.data = data
}
}
}
if (!ecomCart.data._id) {
ecomCart.data._id = randomObjectId()
}
}
export default EcomCart