/**
* Unit tests for FoxHound
*
* @license     MIT
*
* @author      Steven Velozo <steven@velozo.com>
*/

var Chai = require('chai');
var Expect = Chai.expect;
var Assert = Chai.assert;

var libFable = require('fable');
const _Fable = new libFable({Product:'FoxhoundTestsMeadowEndpoints'});
var libFoxHound = require('../source/FoxHound.js');

var _AnimalSchema = (
[
	{ Column: "IDAnimal",        Type:"AutoIdentity" },
	{ Column: "GUIDAnimal",      Type:"AutoGUID" },
	{ Column: "CreateDate",      Type:"CreateDate" },
	{ Column: "CreatingIDUser",  Type:"CreateIDUser" },
	{ Column: "UpdateDate",        Type:"UpdateDate" },
	{ Column: "UpdatingIDUser", Type:"UpdateIDUser" },
	{ Column: "Deleted",         Type:"Deleted" },
	{ Column: "DeletingIDUser",  Type:"DeleteIDUser" },
	{ Column: "DeleteDate",      Type:"DeleteDate" }
]);

var _AnimalSchemaWithoutDeleted = (
[
	{ Column: "IDAnimal",        Type:"AutoIdentity" },
	{ Column: "GUIDAnimal",      Type:"AutoGUID" },
	{ Column: "CreateDate",      Type:"CreateDate" },
	{ Column: "CreatingIDUser",  Type:"CreateIDUser" },
	{ Column: "UpdateDate",        Type:"UpdateDate" },
	{ Column: "UpdatingIDUser", Type:"UpdateIDUser" }
]);

suite
(
	'FoxHound-Dialect-MeadowEndpoints',
	function()
	{
		setup
		(
			function()
			{
			}
		);

		suite
		(
			'Object Sanity',
			function()
			{
				test
				(
					'initialize should build a happy little object',
					function()
					{
						var testFoxHound = libFoxHound.new(_Fable).setDialect('MeadowEndpoints');
						Expect(testFoxHound.dialect.name)
							.to.equal('MeadowEndpoints');
						Expect(testFoxHound)
							.to.be.an('object', 'FoxHound with MeadowEndpoints should initialize as an object directly from the require statement.');
					}
				);
			}
		);

		suite
		(
			'Basic Query Generation',
			function()
			{
				test
				(
					'Create Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setLogLevel(5)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.addRecord({IDAnimal:null, Name:'Foo Foo', Age:15});
						// Build the query
						tmpQuery.buildCreateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Create Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal("Animal");
					}
				);
				test
				(
					'Bad Create Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints');
						// Build the query
						tmpQuery.buildCreateQuery();
						tmpQuery.addRecord({});
						tmpQuery.buildCreateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Create Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal(false);
					}
				);
				test
				(
					'Read Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints').setScope('Animal');
						tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Simple Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/FilteredTo/FSF~Cost~DESC~0');
					}
				);
				test
				(
					'Read Query single record',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints').setScope('Animal');
						tmpQuery.addFilter('IDAnimal', 1);
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Simple Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/1');
					}
				);
				test
				(
					'Read Query single record with sort',
					function()
					{
						// Because we added a sorting clause, this should be a READS
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints').setScope('Animal');
						tmpQuery.addFilter('IDAnimal', 1);
						tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Simple Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/FilteredTo/FBV~IDAnimal~EQ~1~FSF~Cost~DESC~0');
					}
				);
				test
				(
					'Complex Read Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setCap(10)
							.setBegin(0)
							.setDataElements(['Name', 'Age', 'Cost'])
							.setSort([{Column:'Age',Direction:'Ascending'}])
							.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
						tmpQuery.addSort('Cost');
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/LiteExtended/Name,Age,Cost/FilteredTo/FBV~Age~EQ~15~FSF~Age~ASC~0~FSF~Cost~ASC~0/0/10')
					}
				);
				test
				(
					'Complex Read Query 2',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setDataElements(['Name', 'Age', 'Cost'])
							.setCap(100)
							.addFilter('Age', '25')
							.addFilter('', '', '(')
							.addFilter('Color', 'Red')
							.addFilter('Color', 'Green', '=', 'OR')
							.addFilter('', '', ')')
							.addFilter('Description', '', 'IS NOT NULL')
							.addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
						tmpQuery.setLogLevel(3).addSort('Age');
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/LiteExtended/Name,Age,Cost/FilteredTo/FBV~Age~EQ~25~FOP~0~(~0~FBV~Color~EQ~Red~FBVOR~Color~EQ~Green~FCP~0~)~0~FBV~Description~NN~0~FBV~IDOffice~INN~10,11,15,18,22~FSF~Age~ASC~0/0/100');
					}
				);
				test
				(
					'Update Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.addRecord({Age:15,Color:'Brown'});

						// Build the query
						tmpQuery.buildUpdateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Update Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal');
					}
				);
				test
				(
					'Bad Update Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints');

						// Build the query
						tmpQuery.buildUpdateQuery();
						tmpQuery.addRecord({});
						tmpQuery.buildUpdateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Update Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal(false);
					}
				);
				test
				(
					'Delete Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setScope('Animal')
							.addFilter('IDAnimal', 10);

						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildDeleteQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Delete Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/10');
					}
				);
				test
				(
					'Count Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal');

						// Build the query
						tmpQuery.buildCountQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Count Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/Count');
					}
				);
			}
		);

		suite
		(
			'Complex Query Generation - Schemas',
			function()
			{
				test
				(
					'Create Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setLogLevel(5)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.addRecord(
							{
								IDAnimal:false,
								GUIDAnimal:false,
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Deleted:false,
								DeletingIDUser:false,
								DeleteDate:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildCreateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Create Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal("Animal");
					}
				);
				test
				(
					'Create Query -- with GUID specified',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setLogLevel(5)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.addRecord(
							{
								IDAnimal:false,
								GUIDAnimal:'0xabcdef',
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Deleted:false,
								DeletingIDUser:false,
								DeleteDate:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildCreateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Create Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal("Animal");
					}
				);
				test
				(
					'Create Query - with AutoIdentity disabled',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setLogLevel(5)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setDisableAutoIdentity(true)
							.setDisableDeleteTracking(true)
							.setDisableAutoDateStamp(true)
							.setDisableAutoUserStamp(true)
							.addRecord(
							{
								IDAnimal:false,
								GUIDAnimal:false,
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Deleted:false,
								DeletingIDUser:false,
								DeleteDate:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildCreateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Create Query (AutoIdentity disabled)', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal("Animal/WithFlags/DisableAutoDateStamp,DisableDeleteTracking,DisableAutoIdentity,DisableAutoUserStamp");
					}
				);
				test
				(
					'Complex Read Query 2, verify checking Deleted bit with no filters',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setDataElements(['Name', 'Age', 'Cost'])
							.setCap(100);

						//Use a schema that already defines a deleted bit
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/LiteExtended/Name,Age,Cost/0/100');
					}
				);
				test
				(
					'Complex Read Query 2, manually checking Deleted bit with Schema that has one',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setDataElements(['Name', 'Age', 'Cost'])
							.setCap(100)
							.addFilter('Age', '25')
							.addFilter('', '', '(')
							.addFilter('Color', 'Red')
							.addFilter('Color', 'Green', '=', 'OR')
							.addFilter('', '', ')')
							.addFilter('Description', '', 'IS NOT NULL')
							.addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN')
							.addFilter('Deleted', '1');

						//Use a schema that already defines a deleted bit
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/LiteExtended/Name,Age,Cost/FilteredTo/FBV~Age~EQ~25~FOP~0~(~0~FBV~Color~EQ~Red~FBVOR~Color~EQ~Green~FCP~0~)~0~FBV~Description~NN~0~FBV~IDOffice~INN~10,11,15,18,22~FBV~Deleted~EQ~1/0/100');
					}
				);
				test
				(
					'Complex Read Query 2, delete tracking disabled',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable)
							.setDialect('MeadowEndpoints')
							.setScope('Animal')
							.setDisableDeleteTracking(true)
							.setDataElements(['Name', 'Age', 'Cost'])
							.setCap(100);

						//Use a schema that already defines a deleted bit
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildReadQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Select Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animals/LiteExtended/Name,Age,Cost/FilteredTo/FBV~Deleted~GE~0/0/100');
					}
				);
				test
				(
					'Delete Query with Filters',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setScope('Animal')
							.addFilter('IDAnimal', 10);
						//Perform delete with no record specified, but has a Deleted bit in the schema

						//Use a schema that already defines a deleted bit
						tmpQuery.query.schema = _AnimalSchema;

						// Build the query
						tmpQuery.buildDeleteQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Delete Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/10');
					}
				);
				test
				(
					'Update Query -- without Deleted',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.addRecord({
								IDAnimal:82,
								GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
						// Build the query
						tmpQuery.buildUpdateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Update Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal');
					}
				);
				test
				(
					'Update Query -- without Deleted, UpdateDate and UpdatingIDUser',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.setDisableAutoUserStamp(true)
							.setDisableAutoDateStamp(true)
							.addRecord({
								IDAnimal:82,
								GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
						// Build the query
						tmpQuery.buildUpdateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Update Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/WithFlags/DisableAutoDateStamp,DisableAutoUserStamp');
					}
				);
				test
				(
					'Delete Query -- without Deleted',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.addFilter('IDAnimal', 9);
						tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
						// Build the query
						tmpQuery.buildDeleteQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Delete Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/9');
					}
				);
				test
				(
					'Update Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.addFilter('Deleted', 0) //cover case where this can be overridden instead of automatically added
							.addRecord({
								IDAnimal:82,
								GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
								CreateDate:false,
								CreatingIDUser:false,
								UpdateDate:false,
								UpdatingIDUser:false,
								Deleted:false,
								DeletingIDUser:false,
								DeleteDate:false,
								Name:'Froo Froo',
								Age:18
							});
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildUpdateQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Update Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal');
					}
				);
				test
				(
					'Delete Query',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.addFilter('IDAnimal', 9);
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildDeleteQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Delete Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/9');
					}
				);
				test
				(
					'Delete Query with Delete Tracking Disabled',
					function()
					{
						var tmpQuery = libFoxHound.new(_Fable).setDialect('MeadowEndpoints')
							.setLogLevel(5)
							.setScope('Animal')
							.setDisableDeleteTracking(true)
							.addFilter('IDAnimal', 9);
						tmpQuery.query.schema = _AnimalSchema;
						// Build the query
						tmpQuery.buildDeleteQuery();
						// This is the query generated by the MeadowEndpoints dialect
						_Fable.log.trace('Delete Query', tmpQuery.query);
						Expect(tmpQuery.query.body)
							.to.equal('Animal/9');
					}
				);
			}
		);
	}
);
