/*
	Created by Michael Schuijff <michael@reglobe.nl>
	Copyright Lost Images, The Netherlands

	For more information, visit www.michaelschuijff.nl
*/

window.api = window.api || {};

(function () {
	let users = {};
	
	api.get = function (values) {
		if (values.data) {
			let params = encodeURIData(values.data);
			
			if (params) {
				if (!~values.url.indexOf('?')) {
					values.url += '?';
				} else {
					values.url += '&';
				}
				
				values.url += params;
			}
		}
		
		delete values.data;
		
		return request('GET', values);
	}

	api.post = function (values) {
		if (!values.data) {
			delete values.data;
		}
		
		if (values.data && !(values.data instanceof FormData)) {
			values.data = encodeFormData(values.data);
		}
		
		return request('POST', values);
	}

	api.delete = function (values) {
		if (values.data) {
			let params = encodeURIData(values.data);
			
			if (params) {
				if (!~values.url.indexOf('?')) {
					values.url += '?';
				} else {
					values.url += '&';
				}
				
				values.url += params;
			}
		}
		
		delete values.data;

		return request('DELETE', values);
	}
	
	function request (method, values) {
		values = values || {};
		
		let req = new XMLHttpRequest;
		
		values.format = values.format || 'json';
		
		req.onloadend = () => {
			if (!req.status) {
				return;
			}
			
			let contentType = req.getResponseHeader('Content-Type') || '';
			
			if (~contentType.indexOf('application/json')) {
				values.format = 'json';
			}
			
			if (!req.response || req.status != 200) {
				if (values.error) {
					values.error.call(req, req.response, req.status);
				}
				
				if (values.complete) {
					values.complete.call(req);
				}
				
				return;
			}

			if (values.format == 'json' && req.response.error) {
				if (values.error !== undefined) {
					if (values.error) {
						values.error.call(req, req.response.error, req.status);	
					}
				} else if (typeof req.response.error == 'string') {
					toast(req.response.error);
				}
				
				if (values.complete) {
					values.complete.call(req);
				}
				
				return;
			}
			
			if (values.success) {
				values.success.call(req, req.response, req.status);
			}
			
			if (values.complete) {
				values.complete.call(req);
			}
		}
		
		if (values.progress) {
			req.upload.onprogress = (e) => values.progress(e.loaded / e.total * 100);
		}
		
		req.open(method, config.url + values.url);
		
		if (values.format == 'json') {
			req.setRequestHeader('Accept', 'application/json');
		}
		
		if (values.format == 'json' || values.format == 'blob') {
			req.responseType = values.format;
		}

		req.setRequestHeader('Accept-Language', config.language || 'en');

		if ((config.session && values.session !== false) || values.session) {
			let value = 'Bearer: ' + (values.session || config.session);

			let user = values.user || config.user;

			if (user) {
				if (typeof user == 'string') {
					value += '/' + user;
				} else {
					value += '/' + user.id;
				}
			}
			
			req.setRequestHeader('Authorization', value);
		}
		
		req.send(values.data);
		
		return req;
	}
	
	api.error = function (feature, error) {
		if (!feature || !error) {
			return;
		}
		
		if (typeof error == 'object') {
			error = JSON.stringify(error);
		}
		
		console.log('Error ' + feature + ': ' + error);
		
		let data = {
			feature: feature, error: error
		};
		
		if (config.user) {
			data.user_id = config.user.id;
		}
		
		if (config.session) {
			data.session = config.session;
		}
		
		if (window.device) {
			Object.assign(data, {
				platform: device.platform, version: device.version, manufacturer: device.manufacturer
			});
		} else {
			data.platform = 'website';
		}
		
		api.post({
			url: '/report-error', data: data
		});
	}
	
	api.token = function (token) {
		if (!config.session) {
			return;
		}
		
		let values = {
			url: '/session/token', data: { platform: 'browser', token: token }
		};

		if (window.cordova) {
			if (config.android) {
				values.data.platform = 'android';
			}
			
			if (config.iOS) {
				values.data.platform = 'ios';
			}
		}
		
		api.post(values);
	}
	
	api.reset = function () {
		for (let id in users) {
			delete users[id];
		}
	}
		
	api.self = function (user, success, error) {
		if (!config.session || config.offline) {
			error && error();
			return;
		}
		
		api.get({
			url: '/self',
			user: user, 
			success: (result) => {
				let user = result.user;
				
				config.user = Object.assign(users[user.id] || {}, user);
				users[user.id] = config.user;
				
				analytics.push('set', 'user_id', user.id);
				
				success && success(user);
			},
			error: error
		});
	}
	
	api.follow = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}

		user = prepareUser(user);
		
		if (!user || user.following == 'yes') {
			return;
		}

		api.post({
			url: '/user/' + user.id + '/follow',
			success: (result) => {
				let username = getUserName(user);
				
				if (result.pending) {
					user.following = 'pending';
					toast(__('Pending request to follow %s.', username));
				} else {
					Object.assign(user, { following: 'yes', follower_count: result.follower_count });
					toast(__('You\'re following %s.', username));
				}
				
				updateUser(user);
			}
		});
	}

	api.unfollow = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}

		user = prepareUser(user);
		
		if (!user || user.following != 'yes') {
			return;
		}

		api.delete({
			url: '/user/' + user.id + '/follow',
			success: (result) => {
				let username = getUserName(user);
				
				Object.assign(user, { following: 'no', follower_count: result.follower_count });
				toast(__('You unfollowed %s.', username));

				updateUser(user);
			}
		});
	}

	api.cancel = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}

		user = prepareUser(user);
		
		if (!user || user.following != 'pending') {
			return;
		}

		api.delete({
			url: '/user/' + user.id + '/follow',
			success: (result) => {
				let username = getUserName(user);
				
				user.following = 'no';
				toast(__('You cancelled your request to follow %s.', username));
				
				updateUser(user);
			}
		});
	}

	api.accept = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}

		api.post({
			url: '/user/' + user.id + '/accept',
			success: (result) => toast(__('Follow request accepted.'))
		});
	}

	api.decline = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}

		api.post({
			url: '/user/' + user.id + '/decline',
			success: (result) => toast(__('Declined follow request.'))
		});
	}
	
	api.subscribe = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}
		
		api.post({
			url: '/user/' + user.id + '/subscribe',
			success: (result) => {
				let username = getUserName(user);
				
				if (result.pending) {
					Object.assign(user, { subscribed: false, following: 'pending' });
					toast(__('Pending request to follow %s.', username));
				} else {
					Object.assign(user, { subscribed: true, following: 'yes', follower_count: result.follower_count });
					toast(__('You\'re subscribed to %s.', username));
				}
				
				updateUser(user);
			}
		});
	}
	
	api.unsubscribe = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}
		
		api.delete({
			url: '/user/' + user.id + '/subscribe',
			success: (result) => {
				let username = getUserName(user);
				
				Object.assign(user, { subscribed: false });
				toast(__('You unsubscribed from %s.', username));

				updateUser(user);
			}
		});
	}

	api.block = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}
		
		api.post({
			url: '/user/' + user.id + '/block',
			success: (result) => {
				let username = getUserName(user);
				toast(__('You\'ve blocked %s.', username));
				
				let elements = document.querySelectorAll('.post.user-' + user.id + ', .comment.user-' + user.id);
				
				for (let element of elements) {
					let sibling = element.nextSibling;
					
					if (sibling && sibling.classList.contains('comments')) {
						sibling.remove();
					}
					
					element.remove();
				}
				
				cache.delete(['/user/' + user.id, '/user/' + user.id + '/*', '/message/user/' + user.id]);
				
				if (user.username) {
					cache.delete(['/username/' + user.username, '/username/' + user.username + '/*']);
				}
				
				delete users[user.id];
			}
		});
	}

	api.unblock = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = prepareUser(user);

		if (!user) {
			toast(__('User not found.'));
			return;
		}

		api.delete({
			url: '/user/' + user.id + '/block',
			success: () => toast(__('You\'ve unblocked %s.', getUserName(user)))
		});
	}
	
	window.getUser = function (user) {
		if (!user) {
			return false;
		}
		
		if (typeof user == 'string') {
			return users[user] || null;
		}
		
		if (typeof user == 'object') {
			if (users[user.id]) {
				Object.assign(users[user.id], user);
			} else {
				users[user.id] = user;
			}
			
			return users[user.id];
		}
		
		return false;
	}
	
	window.getUserByName = function (username) {
		if (!username) {
			return false;
		}
		
		username = username.toLowerCase();
		
		for (let key in users) {
			let user = users[key];
			
			if (!user.username) {
				continue;
			}
			
			if (user.username.toLowerCase() == username) {
				return user;
			}
		}
		
		return false;
	}
	
	window.getUserName = function (user) {
		user = getUser(user);
		
		if (!user) {
			return null;
		}
		
		return user.name || user.username;
	}
	
	window.updateUser = function (user) {
		let elements = document.querySelectorAll('.user-' + user.id);
		
		for (let element of elements) {
			let classList = element.classList;
			
			classList.toggle('following', user.following == 'yes');
			classList.toggle('pending', user.following == 'pending');
			classList.toggle('subscribed', !!user.subscribed);
			
			let link = element.querySelector('a.followers');
			
			if (!link) {
				continue;
			}
			
			if (user.follower_count == 1) {
				link.innerHTML = '<strong>1</strong> ' + _e('follower');
			} else {
				link.innerHTML = '<strong>' + user.follower_count + '</strong> ' + _e('followers');
			}
		}
	}

	window.prepareUser = function (user) {
		if (!config.user) {
			toast(__('You\'re not logged in.'));
			return;
		}
		
		user = getUser(user);

		if (!user || !user.id) {
			toast(__('User not found.'));
			return;
		}
		
		return user;
	}
})();
