Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// For attribution: [[MediaWiki:Gadget-twinkleblock.js]]
// Block summaries and settings copied from Twinkle's block module.
// Only works for sysop and at [[CAT:UAA]].

$(document).ready(function() {
	'use strict';
	if (mw.config.get('wgPageName').replace(/_/g, ' ') !== 'Category:Wikipedia usernames with possible policy issues' ||
		!mw.config.get('wgUserGroups').includes('sysop')) return; // Non-sysop should not use this.
	
	var AR = {};
	window.AR = AR;
	
	AR.f = function(un) {
		(new mw.Api()).postWithToken('csrf', {
			action: 'block',
			user: un,
			expiry: 'indefinite',
			reason: AR.r,
			autoblock: $('#AR-autoblock').prop('checked'),
			noemail: $('#AR-noemail').prop('checked'),
			allowusertalk: $('#AR-allowusertalk').prop('checked')
		}, {
			async: false
		}).done(function(response) {
			if ($('#AR-blocknotice').prop('checked')) {
				var s = AR.r
					.replace(/\{\{/g, '\{\{subst:')
					.replace(
						/\}\}/g,
						(AR.autoblock ? '|anon=yes' : '') +
						'|time=indefinite' +
						(!AR.allowusertalk ? '|notalk=yes' : '') +
						'sig=yes' +
						'}}');
				console.log(s);
				(new mw.Api()).postWithToken('csrf', {
					action: 'edit',
					title: 'User talk:' + un,
					appendtext: '\n\n' + s,
					summary: AR.es,
					nocreate: AR.nocreate,
					format: 'json'
				}).done(function(r) {
					console.log(r);
					AR.cb();
				}).fail(function(r) {
					console.error(r);
					AR.cb();
				});
			} else {
				AR.cb();
			}
		}).fail(function(f) {
			console.warn(f);
		});
	};
	
	AR.cb = function() {
		$('#AR-counter').text($('#AR-counter').text() - 0 + 1);
	};
	
	AR.p = mw.util.addPortletLink('p-cactions', '', 'MassBlock', 'pt-angrenamer', 'Initialize');
	
	$(AR.p).click(function(e) {
		e.preventDefault();
		
		(new mw.Api()).get({
			action: 'query',
			list: 'categorymembers',
			cmtitle: mw.config.get('wgPageName'),
			cmprop: 'title',
			cmnamespace: [3],
			cmtype: 'page',
			cmlimit: 500,
			format: 'json'
		}).done(function(response) {
			AR.list = response.query.categorymembers;
			AR.usernames = [];
			var j;
			
			for (let i of AR.list) {
				j = i.title.slice(10);
				AR.usernames.push(
					'<label for="AR-usernames-' + j + '" style="display: inline-flex; word-break: break-all;">' +
						'<input type="checkbox" name="AR-usernames" value="' + j + '" class="AR-usernames" \
						id="AR-usernames-' + j + '" style="align-self: center;">' +
						'<span style="padding-left: 0.2em; align-self: center;"> ' + j + '</span>' +
					'</label>'
				);
			}
			
			AR.block = '<button id="AR-block">Block</button>';
			AR.summary = '<input type="text" placeholder="Reason for blocks" id="AR-summary" style="flex-grow: 5;">';
			AR.settings = {};
			AR.settings.arr = [
				{
					i: 'autoblock',
					f: 'Autoblock'
				},
				{
					i: 'noemail',
					f: 'Block email'
				},
				{
					i: 'allowusertalk',
					f: 'Allow editing own talk page'
				},
				{
					i: 'blocknotice',
					f: 'Send block notice'
				}
			];
			AR.settings.select = [
				{
					t: 'uw-botublock',
					c: 'Username implies a bot, soft block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] '+
						'indicates this is a [[WP:BOT|bot]] account, which is currently not approved'
				},
				{
					t: 'uw-botuhblock',
					c: 'Username implies a bot, hard block',
					s: 'You have been indefinitely blocked from editing because your username is a ' +
						'blatant violation of the [[WP:U|username policy]].',
					p: {
						autoblock: true
					}
				},
				{
					t: 'uw-ublock',
					c: 'Username violation, soft block',
					s: 'You have been indefinitely blocked from editing because your username is a ' +
						'violation of the [[WP:U|username policy]]'
				},
				{
					t: 'uw-uhblock',
					c: 'Username violation, hard block',
					s: 'You have been indefinitely blocked from editing because your username is a ' +
						'blatant violation of the [[WP:U|username policy]]',
					p: {
						autoblock: true,
						nocreate: true
					}
				},
				{
					t: 'uw-causeblock',
					c: 'Username represents a non-profit, soft block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' +
						'gives the impression that the account represents a group, organization or website'
				},
				{
					t: 'uw-ublock-wellknown',
					c: 'Username represents a well-known person, soft block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' +
						'matches the name of a well-known living individual'
				},
				{
					t: 'uw-ublock-double',
					c: 'Username closely resembles another user, soft block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' +
						'is too similar to the username of another Wikipedia user'
				},
				{
					t: 'uw-uhblock-double',
					c: 'Attempted impersonation of another user, hard block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' +
						'appears to impersonate another established Wikipedia user',
					p: {
						autoblock: true,
						nocreate: true
					}
				},
				{
					t: 'uw-softerblock',
					c: 'Promotional username, soft block',
					s: 'You have been indefinitely blocked from editing because your [[WP:U|username]] ' +
						'gives the impression that the account represents a group, organization or website'
				},
				{
					t: 'uw-spamublock',
					c: 'Promotional username, promotional edits',
					s: 'You have been indefinitely blocked from editing because your account is being used ' +
						'only for [[WP:SPAM|spam or advertising]] and your username is a violation of the [[WP:U|username policy]]',
					p: {
						autoblock: true,
						nocreate: true
					}
				},
				{
					t: 'uw-spamblacklistblock',
					c: 'editor only attempts to add blacklisted links, see [[Special:Log/spamblacklist]]',
					// s: '',
				},
				{
					t: 'uw-vaublock',
					c: 'Username violation, vandalism-only account',
					s: 'You have been indefinitely blocked from editing because your account is being ' +
						'[[WP:VOA|used only for vandalism]] and your username is a blatant violation of the [[WP:U|username policy]]',
					p: {
						autoblock: true,
						nocreate: true
					}
				}
			];
			AR.settings.f = function(i) {
				return '<label for="AR-' + i.i + '" class="AR-labels" style="display: inline-flex; word-break: break-all;">' +
						'<input type="checkbox" id="AR-' + i.i + '" style="align-self: center;"' +
						(['allowusertalk', 'blocknotice'].includes(i.i) ? ' checked' : '') + '>' +
						'<span style="align-self: center; padding-left: 0.2em; font-size: 0.75em;">' + i.f + '</span>' +
					'</label>';
			};
			AR.settings.list = function() {
				var list = '';
				AR.settings.arr.forEach(function(e) {
					list += AR.settings.f(e);
				});
				return list;
			};
			AR.settings.options = function() {
				var options = [];
				for (let i in AR.settings.select) {
					options.push(
						'<option class="AR-options" value="' + i +'">' +
							AR.settings.select[i].t +
						'</option>'
					);
				}
				return options.join('');
			};
			AR.nocreate = false;
			
			$('#bodyContent').remove();
			$('#firstHeading').after(
				'<div id="AR-wrapper" style="border: 1px solid black; padding: 5px; font-size: 0.75em; font-family: sans-serif;">' +
					'<div id="AR-usernames" style="display: grid; grid-template-columns: auto auto auto auto; padding: 10px;">' +
						AR.usernames.join('') +
					'</div>' +
				'</div>' +
				'<div style="display: flex; flex-wrap: nowrap;">' +
					'<select id="AR-select" style="flex-grow: 1;">' +
						'<option class="AR-options" value="other">' +
							'Other' +
						'</option>' +
						AR.settings.options() +
					'</select>' +
					AR.summary +
				'</div>' +
				'<div style="display: flex; justify-content: space-between;">' +
					AR.block +
					AR.settings.list() +
				'</div>'
			);
			
			// For attribution: https://stackoverflow.com/questions/659508
			$(function() {
				var cbx = $('.AR-usernames');
				var lastChecked = null;
			
				cbx.click(function(e) {
					if (!lastChecked) {
						lastChecked = this;
						return;
					}
			
					if (e.shiftKey) {
						var start = cbx.index(this);
						var end = cbx.index(lastChecked);
			
						cbx.slice(Math.min(start, end), Math.max(start, end) + 1).prop('checked', lastChecked.checked);
					}
			
					lastChecked = this;
				});
			});
			
			$('#AR-select').change(function() {
				if ($(this).val() !== 'other') {
					$('#AR-summary').val(
						'{{' +
							AR.settings.select[$(this).val()].t +
						'}}' +
						' <!-- ' +
							AR.settings.select[$(this).val()].c +
						' -->'
					);
					if (AR.settings.select[$(this).val()].hasOwnProperty('p')) {
						if (AR.settings.select[$(this).val()].p.autoblock) $('#AR-autoblock').prop('checked', true);
						if (AR.settings.select[$(this).val()].p.nocreate) AR.nocreate = true;
					}
				} else {
					$('#AR-summary').val('');
				}
			});
			
			$('#AR-block').click(function(e) {
				e.preventDefault();
				
				$(this).after(
					'<span>Blocked: <span id="AR-counter">' + 0 + '</span> / <span id="AR-selected">' + 0 + '</span></span>'
				);
				$('#AR-selected').text($('input.AR-usernames[type="checkbox"]:checked').length);
				$('[id^=AR-]:not(#AR-counter, #AR-selected), label > ').hide();
				
				AR.r = $('#AR-summary').val();
				AR.es = ($('#AR-select').val() === 'other' ? AR.r : AR.settings.select[$('#AR-select').val()].s);
				AR.checked = [];
				$('input.AR-usernames[type="checkbox"]:checked').each(function() {
					AR.checked.push($(this).val());
				});
				AR.checked.forEach(function(n) {
					AR.f(n, AR.cb);
				});
			});
		});
	});
});