var assert = require('assert');
var _ = require('@sailshq/lodash');

describe('Queryable Interface', function() {
  describe('Nested Query Modifiers', function() {
    describe('with a record', function() {
      before(function(done) {

        // Insert 3 Users
        var users = [];

        // { first_name: 'nested_user1', last_name: 'smith', type: 'odd', age: 8 }
        // { first_name: 'nested_user2', last_name: 'smith', type: 'even', age: 7 }
        // { first_name: 'nested_user3', last_name: 'smith', type: 'odd', age: 6 }
        // { first_name: 'nested_user4', last_name: 'smith', type: 'even', age: 5 }
        // { first_name: 'nested_user5', last_name: 'jones', type: 'odd', age: 4 }
        // { first_name: 'nested_user6', last_name: 'jones', type: 'even', age: 3 }
        // { first_name: 'nested_user7', last_name: 'jones', type: 'odd', age: 2 }
        // { first_name: 'nested_user8', last_name: 'jones', type: 'even', age: 1 }

        for(var i=1; i<=8; i++) {
          users.push({
            first_name: 'nested_user' + i,
            last_name: i <= 4 ? 'smith' : 'jones',
            type: i % 2 ? 'odd' : 'even',
            age: 9 - i
          });
        }

        Queryable.User.createEach(users, function(err, users) {

          if (err) {
            return done(err);
          }

          return done();
        });
      });

      it('should return the correct users', function(done) {
        // Find all users who either:
        // + Have the last name smith, and age <= 7 OR type === "even"
        // + Have the last name jones, and type === "odd" OR first name contains "6"
        Queryable.User.find({ 
          where: { 
            or: [
              { 
                and: [
                  { last_name: 'smith' },
                  { or: 
                    [
                      { age: { '<=': 7 } },
                      { type: 'even' }
                    ]
                  }
                ]
              }, 
              { 
                and: [
                  { last_name: 'jones' },
                  {
                    or: [
                      { type: 'odd' },
                      { first_name: { contains: '6' }}
                    ]
                  }
                ]
              }
            ]
          }
        })
        .sort([{first_name: 'desc'}])
        .exec(function(err, users) {
          if (err) {
            return done(err);
          }

          // Expected results:
          // { first_name: 'nested_user2', last_name: 'smith', type: 'even', age: 7 }
          // { first_name: 'nested_user3', last_name: 'smith', type: 'odd', age: 6 }
          // { first_name: 'nested_user4', last_name: 'smith', type: 'even', age: 5 }
          // { first_name: 'nested_user5', last_name: 'jones', type: 'odd', age: 4 }
          // { first_name: 'nested_user6', last_name: 'jones', type: 'even', age: 3 }
          // { first_name: 'nested_user7', last_name: 'jones', type: 'odd', age: 2 }
          assert(_.isArray(users));
          assert.strictEqual(users.length, 6);
          assert.equal(users[0].first_name, 'nested_user7');
          assert.equal(users[1].first_name, 'nested_user6');
          assert.equal(users[2].first_name, 'nested_user5');
          assert.equal(users[3].first_name, 'nested_user4');
          assert.equal(users[4].first_name, 'nested_user3');
          assert.equal(users[5].first_name, 'nested_user2');

          return done();
        });
      });
    });
  });
});

@@ -1410,16 +1410,37 @@
 ct users
+ with nested criteria
 ', funct
@@ -1447,24 +1447,24 @@
 ion(done) %7B%0A
-
         // F
@@ -1620,16 +1620,18 @@
 %22odd%22 OR
+ (
  first n
@@ -1646,16 +1646,211 @@
 ains %226%22
+ AND age = 1 or age %3C 2 )%0A        // ( (last_name = %22smith%22 AND (age %3C=7 OR type = %22even%22)) OR (last_name = %22jones%22 AND (type = %22odd%22 OR ( first_name like %22%256%25%22 AND ( age = 1 OR age %3C 2 ) ) ) ) )
 %0A       
@@ -2394,39 +2394,366 @@
     
-%7B first_name: %7B contains: '6' %7D
+// %7B first_name: %7Bcontains: '6'%7D%7D%0A                      %7B and: %5B%0A                          %7B first_name: %7B contains: '6' %7D %7D,%0A                          %7B or: %5B%0A                              %7B age: 3 %7D,%0A                              %7B age: %7B '%3C': 4%7D %7D%0A                            %5D %0A                          %7D%0A                        %5D%0A                      
 %7D%0A  

Make nesting test ever so deep