var User = SyncModel.extend({
	sync_type: 'user',

	logged_in: false,
	logging_in: false,
	changing_password: false,

	init: function() {
		this.logged_in = false;
		this.logging_in = false;

		turtl.events.bind('sync:update:user', function(sync_item) {
			if(!this.logged_in) return;
			if(sync_item.item_id != this.id()) return;
			switch(sync_item.action) {
				case 'edit':
					this.reset(sync_item.data);
					break;
			}
		}.bind(this), 'user:sync:update');
		this.bind('destroy', function() {
			turtl.events.unbind('sync:update:user', 'user:sync:update');
		});
	},

	login: function(username, password) {
		this.logging_in = true;
		return turtl.core.send('user:login', username, password)
			.bind(this)
			.then(function(userdata) {
				this.logged_in = true;
				this.set(userdata);
			})
			.finally(function() {
				this.logging_in = false;
			});
	},

	login_from_saved: function(user_id, key) {
		this.logging_in = true;
		return turtl.core.send('user:login-from-saved', user_id, key)
			.bind(this)
			.then(function(userdata) {
				this.logged_in = true;
				this.set(userdata);
			})
			.finally(function() {
				this.logging_in = false;
			});
	},

	save_login: function() {
		return turtl.core.send('user:save-login');
	},

	/**
	 * add a new user.
	 *
	 * note that we don't do the usual model -> local db -> API pattern here
	 * because the local db relies on the user id (which is generated by the
	 * API) and because in the off-chance that there's a failure syncing the
	 * user record after the fact, it could serverely screw some things up in
	 * the client.
	 *
	 * instead, we post to the API, then once we have a full user record that we
	 * know is in the API, we wait for the local DB to init (poll it) and then
	 * add our shiny new user record to it.
	 */
	join: function(username, password)
	{
		this.logging_in = true;
		return turtl.core.send('user:join', username, password)
			.bind(this)
			.then(function(userdata) {
				this.logged_in = true;
				this.set(userdata);
			})
			.finally(function() {
				this.logging_in = false;
			});
	},

	/**
	 * migrate an old account into a new one
	 */
	migrate: function(v6_username, v6_password, username, password) {
		this.logging_in = true;
		return turtl.core.send('user:join-migrate', v6_username, v6_password, username, password)
			.bind(this)
			.then(function(userdata) {
				this.logged_in = true;
				this.set(userdata);
			})
			.finally(function() {
				this.logging_in = false;
			});
	},

	can_migrate: function(username, password) {
		return turtl.core.send('user:can-migrate', username, password);
	},

	/**
	 * Remove a user's account and all their data.
	 */
	delete_account: function(options) {
		return turtl.core.send('user:delete-account');
	},

	/**
	 * change the username/password.
	 */
	change_password: function(cur_username, cur_password, new_username, new_password) {
		return turtl.core.send('user:change-password', cur_username, cur_password, new_username, new_password);
	},

	do_logout: function(options) {
		options || (options = {});
		this.logged_in = false;
		this.clear();
		this.trigger('logout', this);
	},

	logout: function(options)
	{
		options || (options = {});
		return turtl.core.send('user:logout', options.clear_cookie)
			.bind(this)
			.then(function() {
				if(!options.skip_do_logout) this.do_logout(options);
			});
	},

	setting: function(key, val)
	{
		var settings = clone(this.get('settings') || {});
		if(val === undefined) return settings[key];
		settings[key] = val;
		this.set({settings: settings});
		return this.save();
	},

	delete_setting: function(keyspec)
	{
		if(!keyspec) return;
		var settings = clone(this.get('settings') || {});

		var re = new RegExp('^'+keyspec.replace(/\*/g, '.*?')+'$');
		Object.keys(settings).forEach(function(key) {
			if(key.match(re)) delete settings[key];
		});
		this.set({settings: settings});
		return this.save();
	},

	resend_confirmation: function()
	{
		return turtl.core.send('user:resend-confirmation');
	},

	find_by_email: function(email)
	{
		return turtl.core.send('user:find-by-email', email);
	},
});

