    /* <CoffeeScript>

    {utils, Time} = require('tztime')
    functions = require('./functions').functions  # !TODO: Do we need this here?
    {arrayOfMaps_To_CSVStyleArray, csvStyleArray_To_ArrayOfMaps} = require('./dataTransform')  # !TODO: Do we need this here?

    INFINITY = '9999-01-01T00:00:00.000Z'

    class Store
    </CoffeeScript> */
      /**
       * @class Lumenize.Store
       *
       * __An efficient, in-memory, datastore for snapshot data.__
       *
       * Note, this store takes advantage of JavaScript's prototype inheritance to store snapshots in memory. Since the next snapshot might
       * only have one field different from the prior one, this saves a ton of space. There is some concern that this will
       * slow down certain operations because the JavaScript engine has to search all fields in the current level before bumping up
       * to the next. However, there is some evidence that modern JavaScript implementations handle this very efficiently.
       *
       * However, this choice means that each row in the snapshots array doesn't have all of the fields.
       *
       * Store keeps track of all of the fields it has seen so you can flatten a row(s) if necessary.
       *
       * Example:
       *
       *     {Store} = require('../')
       *
       *     snapshotCSVStyleArray = [
       *       ['RecordID', 'DefectID', 'Created_Date', 'Severity', 'Modified_Date', 'Status'],
       *       [         1,          1,   '2014-06-16',          5,    '2014-06-16',    'New'],
       *       [       100,          1,   '2014-06-16',          5,    '2014-07-17',    'In Progress'],
       *       [      1000,          1,   '2014-06-16',          5,    '2014-08-18',    'Done'],
       *     ]
       *
       *     defects = require('../').csvStyleArray_To_ArrayOfMaps(snapshotCSVStyleArray)
       *
       *     config =
       *       uniqueIDField: 'DefectID'
       *       validFromField: 'Modified_Date'
       *       idField: 'RecordID'
       *       defaultValues:
       *         Severity: 4
       *
       *     store = new Store(config, defects)
       *
       *     console.log(require('../').table.toString(store.snapshots, store.fields))
       *     # | Modified_Date            | _ValidTo                 | _PreviousValues | DefectID | RecordID | Created_Date | Severity | Status      |
       *     # | ------------------------ | ------------------------ | --------------- | -------- | -------- | ------------ | -------- | ----------- |
       *     # | 2014-06-16T00:00:00.000Z | 2014-07-17T00:00:00.000Z | [object Object] | 1        | 1        | 2014-06-16   | 5        | New         |
       *     # | 2014-07-17T00:00:00.000Z | 2014-08-18T00:00:00.000Z | [object Object] | 1        | 100      | 2014-06-16   | 5        | In Progress |
       *     # | 2014-08-18T00:00:00.000Z | 9999-01-01T00:00:00.000Z | [object Object] | 1        | 1000     | 2014-06-16   | 5        | Done        |
       *
       * That's pretty boring. We pretty much got out what we put in. There are a few things to notice though. First,
       * Notice how the _ValidTo field is automatically set. Also, notice that it added the _PreviousValues field. This is
       * a record of the immediately proceeding values for the fields that changed. In this way, the records not only
       * represent the current snapshot; they also represent the state transition that occured to get into this snapshot
       * state. That's what stateBoundaryCrossedFilter and other methods key off of.
       *
       * Also, under the covers, the prototype of each snapshot is the prior snapshot and only the fields that changed
       * are actually stored in the next snapshot. So:
       *
       *     console.log(store.snapshots[1] is store.snapshots[2].__proto__)
       *     # true
       *
       * The Store also keeps the equivalent of a database index on uniqueIDField and keeps a pointer to the last snapshot
       * for each particular uniqueIDField. This provides a convenient way to do per entity analysis.
       *
       *     console.log(store.byUniqueID['1'].snapshots[0].RecordID)
       *     # 1
       *
       *     console.log(store.byUniqueID['1'].lastSnapshot.RecordID)
       *     # 1000
       *
       * @constructor
       *
       * @param {Object} config See Config options for details.
       * @param {Object[]} [snapshots] Optional parameter allowing the population of the Store at instantiation.
       *
       * @cfg {String} [uniqueIDField = "_EntityID"] Specifies the field that identifies unique entities.
       * @cfg {String} [validFromField = "_ValidFrom"]
       * @cfg {String} [validToField = "_ValidTo"]
       * @cfg {String} [idField = "_id"]
       * @cfg {String} [tz = "GMT"]
       * @cfg {Object} [defaultValues = {}] In some datastores, null numeric fields may be assumed to be zero and null
       *   boolean fields may be assumed to be false. Lumenize makes no such assumption and will crash if a field value
       *   is missing. the defaultValues becomes the root of prototype inheritance hierarchy.
       *
       */
    /* <CoffeeScript>

    </CoffeeScript> */
      /**
       * @property snapshots
       * @member Lumenize.Store
       * An Array of Objects
       *
       * The snapshots in compressed (via JavaScript inheritance) format
       */
    /* <CoffeeScript>
    </CoffeeScript> */
      /**
       * @property fields
       * @member Lumenize.Store
       * An Array of Strings
       *
       * The list of all fields that this Store has ever seen. Use to expand each row.
       */
    /* <CoffeeScript>
    </CoffeeScript> */
      /**
       * @property byUniqueID
       * @member Lumenize.Store
       * This is the database equivalent of an index by uniqueIDField.
       *
       * An Object in the form:
       *
       *     {
       *       '1234': {
       *         snapshots: [...],
       *         lastSnapshot: <points to last snapshot for this uniqueID>
       *       },
       *       '7890': {
       *         ...
       *       },
       *       ...
       *     }
       */
    /* <CoffeeScript>

        @config = utils.clone(@userConfig)
        unless @config.uniqueIDField?
          @config.uniqueIDField = '_EntityID'
        unless @config.validFromField?
          @config.validFromField = '_ValidFrom'
        unless @config.validToField?
          @config.validToField = '_ValidTo'
        unless @config.tz?
          @config.tz = 'GMT'
        unless @config.defaultValues?
          @config.defaultValues = {}
        @config.defaultValues[@config.validFromField] = new Time(1, Time.MILLISECOND).toString()
        unless @config.idField?
          @config.idField = '_id'

        @snapshots = []

        @fields = [@config.validFromField, @config.validToField, '_PreviousValues', @config.uniqueIDField]
        @lastValidFrom = new Time(1, Time.MILLISECOND).toString()
        @byUniqueID = {}

        @addSnapshots(snapshots)

      addSnapshots: (snapshots) ->
    </CoffeeScript> */
        /**
         * @method addSnapshots
         * @member Lumenize.Store
         *   Adds the snapshots to the Store
         * @param {Object[]} snapshots
         * @chainable
         * @return {Store} Returns this
         *
         */
    /* <CoffeeScript>
        snapshots = utils._.sortBy(snapshots, @config.validFromField)
        for s in snapshots
          uniqueID = s[@config.uniqueIDField]
          utils.assert(uniqueID?, "Missing #{@config.uniqueIDField} field in submitted snapshot: \n" + JSON.stringify(s, null, 2))
          dataForUniqueID = @byUniqueID[uniqueID]

          unless dataForUniqueID?
            # First time we've seen this uniqueID
            dataForUniqueID =
              snapshots: []
              lastSnapshot: @config.defaultValues
            @byUniqueID[uniqueID] = dataForUniqueID

          if s[@config.validFromField] < dataForUniqueID.lastSnapshot[@config.validFromField]
            throw new Error("Got a new snapshot for a time earlier than the prior last snapshot for #{@config.uniqueIDField} #{uniqueID}.")
            # Eventually, we may have to handle this case. I should be able to enable _nextSnapshot and stitch a snapshot in between two existing ones
          else if s[@config.validFromField] is dataForUniqueID.lastSnapshot[@config.validFromField]
            for key, value of s
              dataForUniqueID.lastSnapshot[key] = value
          else
            validFrom = s[@config.validFromField]
            validFrom = new Time(validFrom, null, @config.tz).getISOStringInTZ(@config.tz)
            utils.assert(validFrom >= dataForUniqueID.lastSnapshot[@config.validFromField], "validFromField (#{validFrom}) must be >= lastValidFrom (#{dataForUniqueID.lastSnapshot[@config.validFromField]}) for this entity" ) # !TODO: Deal with out of order snapshots
            utils.assert(validFrom >= @lastValidFrom, "validFromField (#{validFrom}) must be >= lastValidFrom (#{@lastValidFrom}) for the Store")

            validTo = s[@config.validTo]
            if validTo?
              validTo = new Time(validTo, null, @config.tz).getISOStringInTZ(@config.tz)
            else
              validTo = INFINITY

            priorSnapshot = dataForUniqueID.lastSnapshot

            # Build new Snapshot for adding
            newSnapshot = {}
            newSnapshot._PreviousValues = {}
            for key, value of s
              unless key in [@config.validFromField, @config.validToField, '_PreviousValues', @config.uniqueIDField]
                unless key in @fields
                  @fields.push(key)
                unless value == priorSnapshot[key]
                  newSnapshot[key] = value
                  unless key in [@config.idField]

                    if priorSnapshot[key]?
                      newSnapshot._PreviousValues[key] = priorSnapshot[key]
                    else
                      newSnapshot._PreviousValues[key] = null

            newSnapshot[@config.uniqueIDField] = uniqueID
            newSnapshot[@config.validFromField] = validFrom
            newSnapshot[@config.validToField] = validTo
            if s._PreviousValues?
              newSnapshot._PreviousValues = s._PreviousValues
            newSnapshot.__proto__ = priorSnapshot

            # Update priorSnapshot
            if priorSnapshot[@config.validToField] is INFINITY
              priorSnapshot[@config.validToField] = validFrom
            # priorSnapshot._NextSnapshot = newSnapshot  # Adding link to next snapshot in case we want to do smart insertion later

            # Update metadata
            dataForUniqueID.lastSnapshot = newSnapshot
            @lastValidFrom = validFrom

            # Add the newSnapshot to the arrays
            @byUniqueID[uniqueID].snapshots.push(newSnapshot)
            @snapshots.push(newSnapshot)

        return this

      filtered: (filter) ->
    </CoffeeScript> */
        /**
         * @method filtered
         * @member Lumenize.Store
         *   Returns the subset of the snapshots that match the filter
         * @param {Function} filter
         * @return {Object[]} An array of snapshots. Note, they will not be flattened so they have references to their prototypes
         */
    /* <CoffeeScript>
        result = []
        for s in @snapshots
          if filter(s)
            result.push(s)

        return result

      stateBoundaryCrossedFiltered: (field, values, valueToTheRightOfBoundary, forward = true, assumeNullIsLowest = true) ->
    </CoffeeScript> */
        /**
         * @method stateBoundaryCrossedFiltered
         * @member Lumenize.Store
         *   Returns the subset of the snapshots where the field transitions from the left of valueToTheRightOfBoundary to
         *   the right (inclusive)
         * @param {String} field
         * @param {String[]} values
         * @param {String} valueToTheRightOfBoundary
         * @param {Boolean} [forward = true] When true (the default), this will return the transitions from left to right
         *   However, if you set this to false, it will return the transitions right to left.
         * @param {Boolean} [assumeNullIsLowest = true] Set to false if you don't want to consider transitions out of null
         * @return {Object[]} An array or snapshots. Note, they will not be flattened so they have references to their prototypes
         */
    /* <CoffeeScript>
        index = values.indexOf(valueToTheRightOfBoundary)
        utils.assert(index >= 0, "stateToTheRightOfBoundary must be in stateList")
        left = values.slice(0, index)
        if assumeNullIsLowest
          left.unshift(null)
        right = values.slice(index)
        if forward
          filter = (s) -> s._PreviousValues.hasOwnProperty(field) and s._PreviousValues[field] in left and s[field] in right
        else
          filter = (s) -> s._PreviousValues.hasOwnProperty(field) and s._PreviousValues[field] in right and s[field] in left

        return @filtered(filter)

      stateBoundaryCrossedFilteredBothWays: (field, values, valueToTheRightOfBoundary, assumeNullIsLowest = true) ->
    </CoffeeScript> */
        /**
         * @method stateBoundaryCrossedFilteredBothWays
         * @member Lumenize.Store
         *   Shortcut to stateBoundaryCrossedFiltered for when you need both directions
         * @param {String} field
         * @param {String[]} values
         * @param {String} valueToTheRightOfBoundary
         * @param {Boolean} [assumeNullIsLowest = true] Set to false if you don't want to consider transitions out of null
         * @return {Object} An object with two root keys: 1) forward, 2) backward. The values are the arrays that are returned
         *   from stateBoundaryCrossedFiltered
         */
    /* <CoffeeScript>
        forward = @stateBoundaryCrossedFiltered(field, values, valueToTheRightOfBoundary, true, assumeNullIsLowest)
        backward = @stateBoundaryCrossedFiltered(field, values, valueToTheRightOfBoundary, false, assumeNullIsLowest)
        return {forward, backward}

    exports.Store = Store
    </CoffeeScript> */