 _ = require 'lodash'
-expect = require('chai').expect
+Immutable = require 'immutable'
+chai = require('chai')
+expect = chai.expect
+assert = chai.assert
 
 EntityStore = require '../../src/javascript/ecs2/entity_store'
 
 expectArray = (got,expected) ->
   expect(got.length).to.eq expected.length
   expect(got).to.deep.include.members(expected)
+
+expectIs = (actual,expected) ->
+  if !Immutable.is(actual,expected)
+    assert.fail(actual,expected,"Immutable structures not equal.\nExpected: #{expected.toString()}\n  Actual: #{actual.toString()}")
 
 testFindComponents = (estore,filters,expected) ->
   found = []


  describe 'filterObjects', ->
    it 'works', ->
      c1 = { id: 1, name: 'Link', affil: 'good' }
      c2 = { id: 2, name: 'Zelda', affil: 'good' }
      c3 = { id: 3, name: 'Gannon', affil: 'bad' }
      c4 = { id: 4, name: 'Link', affil: 'bad' }

      comps = [c1,c2,c3,c4]

      filter1 = { match: { name: 'Zelda' } }
      found1 = filterObjects comps, filter1
      expectArray found1, [c2]

      filter2 = { match: { affil: 'good' } }
      found2 = filterObjects comps, filter2
      expectArray found2, [c1,c2]
      
      filter3 = { match: { name: 'Link' } }
      found3 = filterObjects comps, filter3
      expectArray found3, [c1,c4]

      filter4 =
        match:
          name: 'Link'
          affil: 'bad'
      
      found4 = filterObjects comps, filter4
      expectArray found4, [c4]

  describe 'joinObjects', ->
    it 'works', ->
      comps = makeZeldaComps()

      charFilter =
        match: { type: 'character' }
        as: 'char'

      boxFilter =
        join: 'char.eid'
        match: { type: 'bbox' }
        as: 'box'

      heroFilter =
        join: 'box.eid'
        match: { type: 'tag', value: 'hero' }
        as: 'hero'

      found1 = joinObjects comps, [charFilter, boxFilter]
      # console.log "RESULTS:",found1
      expectArray found1, [
        { char: comps[1], box: comps[2] }
        { char: comps[5], box: comps[6] }
      ]

      found2 = joinObjects comps, [charFilter,boxFilter,heroFilter]
      # console.log "RESULTS 2:",found2
      expectArray found2, [
        {char: comps[1], box: comps[2], hero: comps[0] }
      ]



  ]


  
filterObjects = (comps,filter) ->
  matchProps = filter.get('match')

  comps.filter (obj) ->
    if Immutable.Map.isMap(obj)
      obj.isSuperset(matchProps)
    else
      _.matches(matchProps.toJS())(obj)

  # cs = _.filter comps, _.matches(matchProps)
  # Immutable.fromJS(cs)

joinObjects = (comps,filters,row=Immutable.Map()) ->
  # console.log "joinObjects(comps,",filters,",",row,")"
  if filters.size == 0
    return Immutable.List([row])

  f0 = convertJoins(filters.first(),row)
  fs = filters.shift()

    
  as = f0.get('as')
  filterObjects(comps,f0).map((c) ->
    joinObjects(comps,fs,row.set(as,c))
  ).flatten(1)
 

convertJoins = (filter,row) ->
  join = filter.get('join')
  if join?
    [refKey,key] = join.split('.')
    refObj = row.get(refKey)
    if refObj
      val = if Immutable.Map.isMap(refObj)
        refObj.get(key)
      else
        refObj[key]

      if val?
        filter.setIn ['match',key], val
      else
        filter
    else
      filter
  else
    filter









################################
query =
  filters: [
    {
      match: { type: 'tag', value: 'hero' }
      as: 'tag'
    }
    "bbox"
    {
      match: { type: 'bbox' }
      join: 'eid'
      as: 'bbox'
    }
    {
      match: { type: 'character' }
      join: 'eid'
      as: 'char'
    }
  ]
# console.log query


# searchComponents comps, ["character", "bbox", "tag:hero"]
