//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/**
* Test suite for all the examples in the readme
*
* NOTE: No, this test suite doesn't use the traditional format for
* a test suite.  This is because the goal is to require as little
* alteration as possible during the copy / paste operation from this test
* suite to the readme file.
*
* @author rod simpson (rod@apigee.com)
*/

$(document).ready(function () {

//call the runner function to start the process
$('#start-button').bind('click', function() {
	$('#start-button').attr("disabled", "disabled");
	$('#test-output').html('');
	runner(0);
});

var logSuccess = true;
var successCount = 0;
var logError = true;
var errorCount = 0;
var logNotice = true;
var _username = 'marty2';
var _email = 'marty2@timetravel.com';
var _password = 'password2';
var _newpassword = 'password3';

var client = new Usergrid.Client({
	orgName:'yourorgname',
	appName:'sandbox',
	logging: true, //optional - turn on logging, off by default
	buildCurl: true //optional - turn on curl commands, off by default
});

client.logout();

function runner(step, arg, arg2){
	step++;
	switch(step)
	{
		case 1:
			notice('-----running step '+step+': DELETE user from DB to prep test');
			clearUser(step);
			break;
		case 2:
			notice('-----running step '+step+': GET test');
			testGET(step);
			break;
		case 3:
			notice('-----running step '+step+': POST test');
			testPOST(step);
			break;
		case 4:
			notice('-----running step '+step+': PUT test');
			testPUT(step);
			break;
		case 5:
			notice('-----running step '+step+': DELETE test');
			testDELETE(step);
			break;
		case 6:
			notice('-----running step '+step+': prepare database - remove all dogs (no real dogs harmed here!!)');
			cleanupAllDogs(step);
			break;
		case 7:
			notice('-----running step '+step+': make a new dog');
			makeNewDog(step);
			break;
		case 8:
			notice('-----running step '+step+': update our dog');
			updateDog(step, arg);
			break;
		case 9:
			notice('-----running step '+step+': refresh our dog');
			refreshDog(step, arg);
			break;
		case 10:
			notice('-----running step '+step+': remove our dog from database (no real dogs harmed here!!)');
			removeDogFromDatabase(step, arg);
			break;
		case 11:
			notice('-----running step '+step+': make lots of dogs!');
			makeSampleData(step, arg);
			break;
		case 12:
			notice('-----running step '+step+': make a dogs collection and show each dog');
			testDogsCollection(step);
			break;
		case 13:
			notice('-----running step '+step+': get the next page of the dogs collection and show each dog');
			getNextDogsPage(step, arg);
			break;
		case 14:
			notice('-----running step '+step+': get the previous page of the dogs collection and show each dog');
			getPreviousDogsPage(step, arg);
			break;
		case 15:
			notice('-----running step '+step+': remove all dogs from the database (no real dogs harmed here!!)');
			cleanupAllDogs(step);
			break;
		case 16:
			notice('-----running step '+step+': prepare database (remove existing user if present)');
			prepareDatabaseForNewUser(step);
			break;
		case 17:
			notice('-----running step '+step+': create a new user');
			createUser(step);
			break;
		case 18:
			notice('-----running step '+step+': update the user');
			updateUser(step, arg);
			break;
		case 19:
			notice('-----running step '+step+': get the existing user');
			getExistingUser(step, arg);
			break;
		case 20:
			notice('-----running step '+step+': refresh the user from the database');
			refreshUser(step, arg);
			break;
		case 21:
			notice('-----running step '+step+': log user in');
			loginUser(step, arg);
			break;
		case 22:
			notice('-----running step '+step+': change users password');
			changeUsersPassword(step, arg);
			break;
		case 23:
			notice('-----running step '+step+': log user out');
			logoutUser(step, arg);
			break;
		case 24:
			notice('-----running step '+step+': relogin user');
			reloginUser(step, arg);
			break;
		case 25:
			notice('-----running step '+step+': logged in user creates dog');
			createDog(step, arg);
			break;
		case 26:
			notice('-----running step '+step+': logged in user likes dog');
			userLikesDog(step, arg, arg2);
			break;
		case 27:
			notice('-----running step '+step+': logged in user removes likes connection to dog');
			removeUserLikesDog(step, arg, arg2);
			break;
		case 28:
			notice('-----running step '+step+': user removes dog');
			removeDog(step, arg, arg2);
			break;
		case 29:
			notice('-----running step '+step+': log the user out');
			logoutUser(step, arg);
			break;
		case 30:
			notice('-----running step '+step+': remove the user from the database');
			destroyUser(step, arg);
			break;
		case 31:
			notice('-----running step '+step+': try to create existing entity');
			createExistingEntity(step, arg);
			break;
		case 32:
			notice('-----running step '+step+': try to create new entity with no name');
			createNewEntityNoName(step, arg);
			break;
		default:
			notice('-----test complete!-----');
			notice('Success count= ' + successCount);
			notice('Error count= ' + errorCount);
			notice('-----thank you for playing!-----');
			$('#start-button').removeAttr("disabled");
	}
}

//logging functions
function success(message){
	successCount++;
	if (logSuccess) {
		console.log('SUCCESS: ' + message);
		var html = $('#test-output').html();
		html += ('SUCCESS: ' + message + '\r\n');
		$('#test-output').html(html);
	}
}

function error(message){
	errorCount++
	if (logError) {
		console.log('ERROR: ' + message);
		var html = $('#test-output').html();
		html += ('ERROR: ' + message + '\r\n');
		$('#test-output').html(html);
	}
}

function notice(message){
	if (logNotice) {
		console.log('NOTICE: ' + message);
		var html = $('#test-output').html();
		html += (message + '\r\n');
		$('#test-output').html(html);
	}
}

//tests
function clearUser(step) {
  var options = {
    method:'DELETE',
    endpoint:'users/fred'
  };
  client.request(options, function (err, data) {
    //data will contain raw results from API call
    success('User cleared from DB');
    runner(step);
  });
}

function testGET(step) {
	var options = {
		method:'GET',
		endpoint:'users'
	};
	client.request(options, function (err, data) {
		if (err) {
			error('GET failed');
		} else {
			//data will contain raw results from API call
			success('GET worked');
			runner(step);
		}
	});
}

function testPOST(step) {
	var options = {
		method:'POST',
		endpoint:'users',
		body:{ username:'fred', password:'secret' }
	};
	client.request(options, function (err, data) {
		if (err) {
			error('POST failed');
		} else {
			//data will contain raw results from API call
			success('POST worked');
			runner(step);
		}
	});
}

function testPUT(step) {
	var options = {
		method:'PUT',
		endpoint:'users/fred',
		body:{ newkey:'newvalue' }
	};
	client.request(options, function (err, data) {
		if (err) {
			error('PUT failed');
		} else {
			//data will contain raw results from API call
			success('PUT worked');
			runner(step);
		}
	});
}

function testDELETE(step) {
	var options = {
		method:'DELETE',
		endpoint:'users/fred'
	};
	client.request(options, function (err, data) {
		if (err) {
			error('DELETE failed');
		} else {
			//data will contain raw results from API call
			success('DELETE worked');
			runner(step);
		}
	});
}

function makeNewDog(step) {

	var options = {
		type:'dogs',
		name:'Rocky'
	}

	client.createEntity(options, function (err, dog) {
		if (err) {
			error('dog not created');
		} else {
			success('dog is created');

			//once the dog is created, you can set single properties:
			dog.set('breed','Dinosaur');

			//the set function can also take a JSON object:
			var data = {
				master:'Fred',
				state:'hungry'
			}
			//set is additive, so previously set properties are not overwritten
			dog.set(data);

			//finally, call save on the object to save it back to the database
			dog.save(function(err){
				if (err){
					error('dog not saved');
				} else {
					success('new dog is saved');
					runner(step, dog);
				}
			});
		}
	});

}

function updateDog(step, dog) {

	//change a property in the object
	dog.set("state", "fed");
	//and save back to the database
	dog.save(function(err){
		if (err){
			error('dog not saved');
		} else {
			success('dog is saved');
			runner(step, dog);
		}
	});

}

function refreshDog(step, dog){

	//call fetch to refresh the data from the server
	dog.fetch(function(err){
		if (err){
			error('dog not refreshed from database');
		} else {
			//dog has been refreshed from the database
			//will only work if the UUID for the entity is in the dog object
			success('dog entity refreshed from database');
			runner(step, dog);
		}
	});

}

function removeDogFromDatabase(step, dog){

	//the destroy method will delete the entity from the database
	dog.destroy(function(err){
		if (err){
			error('dog not removed from database');
		} else {
			success('dog removed from database'); // no real dogs were harmed!
			dog = null; //no real dogs were harmed!
			runner(step, 1);
		}
	});

}

function makeSampleData(step, i) {
	notice('making dog '+i);

	var options = {
		type:'dogs',
		name:'dog'+i,
		index:i
	}

	client.createEntity(options, function (err, dog) {
		if (err) {
			error('dog ' + i + ' not created');
		} else {
			if (i >= 30) {
				//data made, ready to go
				success('all dogs made');
				runner(step);
			} else {
				success('dog ' + i + ' made');
				//keep making dogs
				makeSampleData(step, ++i);
			}
		}
	});
}

function testDogsCollection(step) {

	var options = {
		type:'dogs',
		qs:{ql:'order by index'}
	}

	client.createCollection(options, function (err, dogs) {
		if (err) {
			error('could not make collection');
		} else {

			success('new Collection created');

			//we got the dogs, now display the Entities:
			while(dogs.hasNextEntity()) {
				//get a reference to the dog
				dog = dogs.getNextEntity();
				var name = dog.get('name');
				notice('dog is called ' + name);
			}

			success('looped through dogs');

			//create a new dog and add it to the collection
			var options = {
				name:'extra-dog',
				fur:'shedding'
			}
			//just pass the options to the addEntity method
			//to the collection and it is saved automatically
			dogs.addEntity(options, function(err, dog, data) {
				if (err) {
					error('extra dog not saved or added to collection');
				} else {
					success('extra dog saved and added to collection');
					runner(step, dogs);
				}
			});
		}
	});

}

function getNextDogsPage(step, dogs) {

	if (dogs.hasNextPage()) {
		//there is a next page, so get it from the server
		dogs.getNextPage(function(err){
			if (err) {
				error('could not get next page of dogs');
			} else {
				success('got next page of dogs');
				//we got the next page of data, so do something with it:
				var i = 11;
				while(dogs.hasNextEntity()) {
					//get a reference to the dog
					var dog = dogs.getNextEntity();
					var index = dog.get('index');
					if(i !== index) {
						error('wrong dog loaded: wanted' + i + ', got ' + index);
					}
					notice('got dog ' + i);
					i++
				}
				success('looped through dogs')
				runner(step, dogs);
			}
		});
	} else {
		getPreviousDogsPage(dogs);
	}

}

function getPreviousDogsPage(step, dogs) {

	if (dogs.hasPreviousPage()) {
		//there is a previous page, so get it from the server
		dogs.getPreviousPage(function(err){
			if(err) {
				error('could not get previous page of dogs');
			} else {
				success('got next page of dogs');
				//we got the previous page of data, so do something with it:
				var i = 1;
				while(dogs.hasNextEntity()) {
					//get a reference to the dog
					var dog = dogs.getNextEntity();
					var index = dog.get('index');
					if(i !== index) {
						error('wrong dog loaded: wanted' + i + ', got ' + index);
					}
					notice('got dog ' + i);
					i++
				}
				success('looped through dogs');
				runner(step);
			}
		});
	} else {
		getAllDogs();
	}
}

function cleanupAllDogs(step){

	var options = {
		type:'dogs',
		qs:{limit:50} //limit statement set to 50
	}

	client.createCollection(options, function (err, dogs) {
		if (err) {
			error('could not get all dogs');
		} else {
			success('got at most 50 dogs');
			//we got 50 dogs, now display the Entities:
			while(dogs.hasNextEntity()) {
				//get a reference to the dog
				var dog = dogs.getNextEntity();
				var name = dog.get('name');
				notice('dog is called ' + name);
			}
			dogs.resetEntityPointer();
			//do doggy cleanup
			while(dogs.hasNextEntity()) {
				//get a reference to the dog
				var dog = dogs.getNextEntity();
				var dogname = dog.get('name');
				notice('removing dog ' + dogname + ' from database');
				dog.destroy(function(err, data) {
					if (err) {
						error('dog not removed');
					} else {
						success('dog removed');
					}
				});
			}

			//no need to wait around for dogs to be removed, so go on to next test
			runner(step);
		}
	});
}


function prepareDatabaseForNewUser(step) {
	var options = {
		method:'DELETE',
		endpoint:'users/'+_username
	};
	client.request(options, function (err, data) {
		if (err) {
			notice('database ready - no user to delete');
		runner(step);
		} else {
			//data will contain raw results from API call
			success('database ready - user deleted worked');
			runner(step);
		}
	});
}


function createUser(step) {
	client.signup(_username, _password, _email, 'Marty McFly',
		function (err, marty) {
			if (err){
				error('user not created');
				runner(step, marty);
			} else {
				success('user created');
				runner(step, marty);
			}
		}
	);
}

function updateUser(step, marty) {

	//add properties cumulatively
	marty.set('state', 'California');
	marty.set("girlfriend","Jennifer");
	marty.save(function(err){
		if (err){
			error('user not updated');
		} else {
			success('user updated');
			runner(step, marty);
		}
	});

}

function getExistingUser(step, marty) {

	var options = {
		type:'users',
		username:_username
	}
	client.getEntity(options, function(err, existingUser){
		if (err){
			error('existing user not retrieved');
		} else {
			success('existing user was retrieved');

			var username = existingUser.get('username');
			if (username === _username){
				success('got existing user username');
			} else {
				error('could not get existing user username');
			}
			runner(step, marty);
		}
	});

}


function refreshUser(step, marty) {

	marty.fetch(function(err){
		if (err){
			error('not refreshed');
		} else {
			success('user refreshed');
			runner(step, marty);
		}
	});

}

function loginUser(step, marty) {
	username = _username;
	password = _password;
	client.login(username, password,
		function (err) {
			if (err) {
				error('could not log user in');
			} else {
				success('user has been logged in');

				//the login call will return an OAuth token, which is saved
				//in the client. Any calls made now will use the token.
				//once a user has logged in, their user object is stored
				//in the client and you can access it this way:
				var token = client.token;

				//Then make calls against the API.  For example, you can
				//get the user entity this way:
				client.getLoggedInUser(function(err, data, user) {
					if(err) {
						error('could not get logged in user');
					} else {
						success('got logged in user');

						//you can then get info from the user entity object:
						var username = user.get('username');
						notice('logged in user was: ' + username);

						runner(step, user);
					}
				});

			}
		}
	);
}

function changeUsersPassword(step, marty) {

	marty.set('oldpassword', _password);
	marty.set('newpassword', _newpassword);
	marty.save(function(err){
		if (err){
			error('user password not updated');
		} else {
			success('user password updated');
			runner(step, marty);
		}
	});

}

function logoutUser(step, marty) {

	//to log the user out, call the logout() method
	client.logout();

	//verify the logout worked
	if (client.isLoggedIn()) {
		error('logout failed');
	} else {
		success('user has been logged out');
	}

	runner(step, marty);
}

function reloginUser(step, marty) {

	username = _username
	password = _newpassword;
	client.login(username, password,
		function (err) {
		if (err) {
			error('could not relog user in');
		} else {
			success('user has been re-logged in');
			runner(step, marty);
		}
		}
	);
}



//TODO: currently, this code assumes permissions have been set to support user actions.  need to add code to show how to add new role and permission programatically
//
//first create a new permission on the default role:
//POST "https://api.usergrid.com/yourorgname/yourappname/roles/default/permissions" -d '{"permission":"get,post,put,delete:/dogs/**"}'
//then after user actions, delete the permission on the default role:
//DELETE "https://api.usergrid.com/yourorgname/yourappname/roles/default/permissions?permission=get%2Cpost%2Cput%2Cdelete%3A%2Fdogs%2F**"


function createDog(step, marty) {

	var options = {
		type:'dogs',
		name:'einstein',
		breed:'mutt'
	}

	client.createEntity(options, function (err, dog) {
		if (err) {
			error('POST new dog by logged in user failed');
		} else {
			success('POST new dog by logged in user succeeded');
			runner(step, marty, dog);
		}
	});

}

function userLikesDog(step, marty, dog) {

	marty.connect('likes', dog, function (err, data) {
		if (err) {
			error('connection not created');
			runner(step, marty);
		} else {

			//call succeeded, so pull the connections back down
			marty.getConnections('likes', function (err, data) {
				if (err) {
						error('could not get connections');
				} else {
					//verify that connection exists
					if (marty.likes.einstein) {
						success('connection exists');
					} else {
						error('connection does not exist');
					}

					runner(step, marty, dog);
				}
			});
		}
	});

}

function removeUserLikesDog(step, marty, dog) {

	marty.disconnect('likes', dog, function (err, data) {
		if (err) {
			error('connection not deleted');
			runner(step, marty);
		} else {

			//call succeeded, so pull the connections back down
			marty.getConnections('likes', function (err, data) {
				if (err) {
					error('error getting connections');
				} else {
					//verify that connection exists
					if (marty.likes.einstein) {
						error('connection still exists');
					} else {
						success('connection deleted');
					}

					runner(step, marty, dog);
				}
			});
		}
	});

}

function removeDog(step, marty, dog) {

	//now delete the dog from the database
	dog.destroy(function(err, data) {
		if (err) {
			error('dog not removed');
		} else {
			success('dog removed');
		}
	});
	runner(step, marty);
}

function destroyUser(step, marty) {

	marty.destroy(function(err){
		if (err){
			error('user not deleted from database');
		} else {
			success('user deleted from database');
			marty = null; //blow away the local object
			runner(step);
		}
	});

}

function createExistingEntity(step, marty) {

	var options = {
		type:'dogs',
		name:'einstein'
	}

	client.createEntity(options, function (err, dog) {
		if (err) {
			error('Create new entity to use for existing entity failed');
		} else {
			success('Create new entity to use for existing entity succeeded');

			var uuid = dog.get('uuid');
			//now create new entity, but use same entity name of einstein.  This means that
			//the original einstein entity now exists.  Thus, the new einstein entity should
			//be the same as the original + any data differences from the options var:

			options = {
				type:'dogs',
				name:'einstein',
				breed:'mutt'
			}
			client.createEntity(options, function (err, newdog) {
				if (err) {
					error('Create new entity to use for existing entity failed');
				} else {
					success('Create new entity to use for existing entity succeeded');

					var newuuid = newdog.get('uuid');
					if (newuuid === uuid) {
						success('UUIDs of new and old entities match');
					} else {
						error('UUIDs of new and old entities do not match');
					}

					var breed = newdog.get('breed');
					if (breed === 'mutt') {
						success('attribute sucesfully set on new entity');
					} else {
						error('attribute not sucesfully set on new entity');
					}

					newdog.destroy(function(err){
						if (err){
							error('existing entity not deleted from database');
						} else {
							success('existing entity deleted from database');
							dog = null; //blow away the local object
							newdog = null; //blow away the local object
							runner(step);
						}
					});

				}
			});
		}
	});

}

function createNewEntityNoName(step, marty) {

	var options = {
   type:"something",
   othervalue:"something else"
	}

	client.createEntity(options, function (err, entity) {
		if (err) {
			error('Create new entity with no name failed');
		} else {
			success('Create new entity with no name succeeded');

      entity.destroy();
      runner(step);
		}
	});

}

});