# accumulate_distribute/events/data_managed_candles.js

    'use strict'

    const _reverse = require('lodash/reverse')
    const hasIndicatorOffset = require('../util/has_indicator_offset')
    const hasIndicatorCap = require('../util/has_indicator_cap')
    const parseChannelKey = require('../../util/parse_channel_key')

    /**
     * If the instance has internal indicators, they are either seeded with the
     * initial candle dataset or updated with new candles as they arrive. The
     * candle dataset is saved on the instance state for order generation.
     *
     * @memberOf module:AccumulateDistribute
     * @listens AOHost~event:dataManagedCandles
     * @see module:AccumulateDistribute.hasIndicatorOffset
     * @see module:AccumulateDistribute.hasIndicatorCap
     *
     * @param {AOInstance} instance - AO instance state
     * @param {object[]} candles - array of incoming candles
     * @param {EventMetaInformation} meta - source channel information
     * @returns {Promise} p
     */
    const onDataManagedCandles = async (instance = {}, candles, meta) => {
      const { state = {}, h = {} } = instance
      const { args = {}, offsetIndicator, capIndicator } = state
      const { symbol, relativeOffset, relativeCap } = args
      const { debug, updateState } = h
      const { chanFilter } = meta
      const { key } = chanFilter
      const { symbol: chanSymbol } = parseChannelKey(key)

      if ((!hasIndicatorOffset(args) && !hasIndicatorCap(args)) || symbol !== chanSymbol) {
        return
      }

      const [lastCandle] = candles

      // Both indicators start with 0 length
      if ((capIndicator && capIndicator.l() === 0) || (offsetIndicator && offsetIndicator.l() === 0)) {
        debug('seeding indicators with %d candle prices', candles.length)

        const orderedCandles = _reverse(candles)
        orderedCandles.forEach((candle) => {
          if (hasIndicatorCap(args)) {
            capIndicator.add(candle[relativeCap.candlePrice])
          }

          if (hasIndicatorOffset(args)) {
            offsetIndicator.add(candle[relativeOffset.candlePrice])
          }
        })
      } else { // add new data point/update data point
        if (hasIndicatorOffset(args)) {
          const price = lastCandle[relativeOffset.candlePrice]

          debug('updating relative offset indicator with candle price %f', price)

          if (!state.lastCandle) {
            offsetIndicator.add(price)
          } else if (state.lastCandle.mts === lastCandle.mts) {
            offsetIndicator.update(price)
          } else {
            offsetIndicator.add(price)
          }
        }

        if (hasIndicatorCap(args)) {
          const price = lastCandle[relativeCap.candlePrice]

          debug('updating relative cap indicator with candle price %f', price)

          if (!state.lastCandle) {
            capIndicator.add(price)
          } else if (state.lastCandle.mts === lastCandle.mts) {
            capIndicator.update(price)
          } else {
            capIndicator.add(price)
          }
        }
      }

      await updateState(instance, { candles })
    }

    module.exports = onDataManagedCandles