(function($) {

/*

Twinkle.prod = function twinkleprod {
	/* 기능 비활성화 : 아직 준비 안 됨 (2020-08-12) */
	if (true) {
		return;

	if ((([0, 6, 108].indexOf(mw.config.get('wgNamespaceNumber')) === -1) && (mw.config.get('wgNamespaceNumber') !== 2 || mw.config.get('wgCategories').indexOf('Wikipedia books (user books)') === -1))
		return;

	Twinkle.addPortletLink;

// Used in edit summaries, for comparisons, etc.
var namespace;

Twinkle.prod.callback = function twinkleprodCallback {
	Twinkle.prod.defaultReason = Twinkle.getPref('prodReasonDefault');

	switch (mw.config.get('wgNamespaceNumber')) {
		case 0:
			namespace = 'article';
			break;
		case 6:
			namespace = 'file';
			break;
		case 2:
		case 108:
			namespace = 'book';
			break;
		// no default

	var Window = new Morebits.simpleWindow;
	Window.setTitle('Proposed deletion (PROD)');
	Window.setScriptName('Twinkle');

	var form = new Morebits.quickForm(Twinkle.prod.callback.evaluate);

	if (namespace === 'article') {
		Window.addFooterLink;
		Window.addFooterLink;
		Window.addFooterLink;
		Window.addFooterLink('Proposed deletion (books) policy', 'WP:BOOKPROD');

	var field = form.append({
		type: 'field',
		label: 'PROD type',
		id: 'prodtype_fieldset'

	field.append({
		type: 'radio',
		name: 'prodtype',
		event: Twinkle.prod.callback.prodtypechanged,
		list: [
				label: 'PROD (proposed deletion)',
				value: 'prod',
				checked: true,
				tooltip: 'Normal proposed deletion, per WP:PROD'
				label: 'BLP PROD (proposed deletion of unsourced BLPs)',
				value: 'prodblp',
				tooltip: 'Proposed deletion of new, completely unsourced biographies of living persons, per WP:BLPPROD'
		]

	// Placeholder fieldset to be replaced in Twinkle.prod.callback.prodtypechanged
	form.append({
		type: 'field',
		name: 'parameters'

	Window.addFooterLink;

	form.append;

	var result = form.render;
	Window.setContent(result);
	Window.display;

	// Hide fieldset for File and Book PROD types since only normal PROD is allowed
	if (namespace !== 'article') {
		$(result).find('#prodtype_fieldset').hide;

	// Fake a change event on the first prod type radio, to initialize the type-dependent controls
	var evt = document.createEvent('Event');
	evt.initEvent;
	result.prodtype[0].dispatchEvent(evt);


Twinkle.prod.callback.prodtypechanged = function(event) {
	// prepare frame for prod type dependant controls
	var field = new Morebits.quickForm.element({
		type: 'field',
		label: 'Parameters',
		name: 'parameters'
	// create prod type dependant controls
	switch (event.target.values) {
		case 'prod':
			field.append({
				type: 'checkbox',
				list: [
						label: 'Notify page creator if possible',
						value: 'notify',
						name: 'notify',
						tooltip: "A notification template will be placed on the creator's talk page if this is true.",
						checked: true
				]
			field.append({
				type: 'textarea',
				name: 'reason',
				label: 'Reason for proposed deletion:',
				value: Twinkle.prod.defaultReason
			break;

		case 'prodblp':
			// first, remember the prod value that the user entered in the textarea, in case they want to switch back. We can abuse the config field for that.
			if (event.target.form.reason) {
				Twinkle.prod.defaultReason = event.target.form.reason.value;

			field.append({
				type: 'checkbox',
				list: [
						label: 'Notify page creator if possible',
						value: 'notify',
						name: 'notify',
						tooltip: 'Creator of article has to be notified.',
						checked: true,
						disabled: true
				]
			// temp warning, can be removed down the line once BLPPROD is more established. Amalthea, May 2010.
			var boldtext = document.createElement('b');
			boldtext.appendChild(document.createTextNode);
			field.append({
				type: 'div',
				label: boldtext
			break;

		default:
			break;

	event.target.form.replaceChild(field.render, $(event.target.form).find('fieldset[name="parameters"]')[0]);

Twinkle.prod.callbacks = {
	checkpriors: function(apiobj) {
		var xmlDoc = apiobj.responseXML;
		var statelem = apiobj.statelem;
		var params = apiobj.params;

		// Check talk page for templates indicating prior XfD or PROD
		var numTemplates = $(xmlDoc).find('templates tl').length;
		if (numTemplates) {
			var template = $(xmlDoc).find('templates tl')[0].getAttribute('title');
			if (numTemplates === 1 && template === 'Template:Old prod') {
				params.oldProdPresent = true; // Mark for reference later, when deciding if to endorse
			// if there are multiple templates, at least one of them would be a prior xfd template
				statelem.warn;
				return;

		var ts = new Morebits.wiki.page(mw.config.get('wgPageName'));
		ts.setFollowRedirect(true); // for NPP, and also because redirects are ineligible for PROD
		ts.setCallbackParameters(params);
		ts.setLookupNonRedirectCreator(true); // Look for author of first non-redirect revision
		ts.lookupCreation(Twinkle.prod.callbacks.creationInfo);

	creationInfo: function(pageobj) {
		var params = pageobj.getCallbackParameters;
		params.initialContrib = pageobj.getCreator;
		params.creation = pageobj.getCreationTimestamp;

		Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
		Morebits.wiki.actionCompleted.notice = 'Tagging complete';

		var wikipedia_page = new Morebits.wiki.page(mw.config.get('wgPageName'), 'Tagging page');
		wikipedia_page.setFollowRedirect(true); // for NPP, and also because redirects are ineligible for PROD
		wikipedia_page.setCallbackParameters(params);
		wikipedia_page.load(Twinkle.prod.callbacks.main);

	main: function(pageobj) {
		var statelem = pageobj.getStatusElement;

		if (!pageobj.exists) {
			statelem.error("It seems that the page doesn't exist. Perhaps it has already been deleted.");
			return;

		var text = pageobj.getPageText;
		var params = pageobj.getCallbackParameters;

		// Check for already existing deletion tags
		var tag_re = /{{(?:db-?|delete|article for deletion\/dated|ffd\b)|#invoke:RfD/i;
		if (tag_re.test(text)) {
			statelem.warn;
			return;

		// Remove tags that become superfluous with this action
		text = text.replace(/{{\s*(userspace draft|mtc|(copy|move) to wikimedia commons|(copy |move )?to ?commons)\s*(\|(?:{{[^{}]*}}|[^{}])*)?}}\s*/gi, '');
		var prod_re = /{{\s*(?:Prod blp|Proposed deletion|book-prod)\/dated(?: files)?\s*\|(?:{{[^{}]*}}|[^{}])*}}/i;
		var summaryText;

		if (!prod_re.test(text)) {

			// Page previously PROD-ed
			if (params.oldProdPresent) {
				if (params.blp) {
					if (!confirm('Previous PROD nomination found on talk page. Do you still want to continue applying BLPPROD? ')) {
						statelem.warn;
						return;
					statelem.info;
					statelem.warn;
					return;

			// Alert if article is at least three days old, not in Category:Living people, and BLPPROD is selected
			if (params.blp) {
				var isMoreThan3DaysOld = new Morebits.date(params.creation).add.isAfter(new Date(pageobj.getLoadTime));
				var blpcheck_re = /\[\[Category:Living people\]\]/i;
				if (!blpcheck_re.test(text) && isMoreThan3DaysOld) {
					if (!confirm) {
						return;

			// Notification to first contributor
			if (params.usertalk) {
				// Disallow warning yourself
				if (params.initialContrib === mw.config.get('wgUserName')) {
					statelem.warn('You (' + params.initialContrib + ') created this page; skipping user notification');
					if (Twinkle.getPref('logProdPages')) {
						Twinkle.prod.callbacks.addToLog(params);
					// Template:Proposed deletion notify supports File namespace
					var notifyTemplate;
					if (params.blp) {
						notifyTemplate = 'prodwarningBLP';
						notifyTemplate = 'bprodwarning';
						notifyTemplate = 'proposed deletion notify';
					var notifytext = '\n ~~~~';

					var usertalkpage = new Morebits.wiki.page('User talk:' + params.initialContrib, 'Notifying initial contributor (' + params.initialContrib + ')');
					usertalkpage.setAppendText(notifytext);
					usertalkpage.setEditSummary('Notification: proposed deletion of :' + Morebits.pageNameNorm + '.' + Twinkle.getPref('summaryAd'));
					usertalkpage.setCreateOption('recreate');
					usertalkpage.setFollowRedirect;
					usertalkpage.setCallbackParameters(params);
					usertalkpage.append(function onNotifySuccess {
						// add nomination to the userspace log, if the user has enabled it
						if (Twinkle.getPref('logProdPages')) {
							params.logInitialContrib = params.initialContrib;
							Twinkle.prod.callbacks.addToLog(params);
						// if user could not be notified, log nomination without mentioning that notification was sent
						if (Twinkle.getPref('logProdPages')) {
							Twinkle.prod.callbacks.addToLog(params);
				Twinkle.prod.callbacks.addToLog(params);
			var tag;
			if (params.blp) {
				summaryText = 'Proposing article for deletion per WP:BLPPROD.';
				tag = '';
				summaryText = 'Proposing book for deletion per WP:BOOKPROD.';
				tag = '';
				summaryText = 'Proposing ' + namespace + ' for deletion per WP:PROD.';
				tag = '';

			// Insert tag after short description or any hatnotes
			var wikipage = new Morebits.wikitext.page(text);
			text = wikipage.insertAfterTemplates.getText;

			// Add to the talk page
			if (!params.oldProdPresent) {
				var oldprodfull = '}}\n';
				var talktitle = new mw.Title(mw.config.get('wgPageName')).getTalkPage.getPrefixedText;
				var talkpage = new Morebits.wiki.page;
				talkpage.setPrependText(oldprodfull);
				talkpage.setEditSummary('Adding ' + Twinkle.getPref('summaryAd'));
				talkpage.setFollowRedirect(true); // match behavior for page tagging
				talkpage.setCreateOption('recreate');
				talkpage.prepend;
			var prod2_re = //i;
			if (prod2_re.test(text)) {
				statelem.warn;
				return;
			var confirmtext = 'A tag was already found on this page. \nWould you like to add a tag with your explanation?';
			if (params.blp && !/ tag was found on this article.\nWould you like to add a tag with explanation "article is a biography of a living person with no sources"?';
			if (!confirm(confirmtext)) {
				statelem.warn('Aborted per user request');
				return;

			summaryText = 'Endorsing proposed deletion per WP:' + (params.blp ? 'BLP' : params.book ? 'BOOK' : '') + 'PROD.';
			text = text.replace(prod_re, text.match(prod_re) + '\n\n');

			if (Twinkle.getPref('logProdPages')) {
				params.logEndorsing = true;
				Twinkle.prod.callbacks.addToLog(params);

		// curate/patrol the page
		if (Twinkle.getPref('markProdPagesAsPatrolled')) {
			pageobj.triage;

		pageobj.setPageText(text);
		pageobj.setEditSummary(summaryText + Twinkle.getPref('summaryAd'));
		pageobj.setWatchlist(Twinkle.getPref('watchProdPages'));
		pageobj.setCreateOption('nocreate');
		pageobj.save;

	addToLog: function(params) {
		var usl = new Morebits.userspaceLogger(Twinkle.getPref('prodLogPageName'));
		usl.initialText =
			"This is a log of all proposed deletion tags applied or endorsed by this user using Twinkle's PROD module.\n\n" +
			'If you no longer wish to keep this log, you can turn it off using the preferences panel, and ' +
			'nominate this page for speedy deletion under CSD U1.\n';

		var logText = '# :' + Morebits.pageNameNorm + '';
		var summaryText;
		// If a logged file is deleted but exists on commons, the wikilink will be blue, so provide a link to the log
		logText += namespace === 'file' ? ' ([ log]): ' : ': ';
		if (params.logEndorsing) {
			logText += 'endorsed ' + (params.blp ? 'BLP ' : params.book ? 'BOOK' : '') + 'PROD. ~~~~~';
			if (params.reason) {
				logText += "\n#* **Reason**: " + params.reason + '\n';
			summaryText = 'Logging endorsement of PROD nomination of :' + Morebits.pageNameNorm + '.';
			logText += (params.blp ? 'BLP ' : params.book ? 'BOOK' : '') + 'PROD';
			if (params.logInitialContrib) {
				logText += '; notified ';
			logText += ' ~~~~~\n';
			if (!params.blp && params.reason) {
				logText += "#* **Reason**: " + params.reason + '\n';
			summaryText = 'Logging PROD nomination of :' + Morebits.pageNameNorm + '.';

		usl.log(logText, summaryText + Twinkle.getPref('summaryAd'));


Twinkle.prod.callback.evaluate = function twinkleprodCallbackEvaluate(e) {
	var form = e.target;
	var input = Morebits.quickForm.getInputData(form);

	var params = {
		usertalk: input.notify,
		blp: input.prodtype === 'prodblp',
		book: namespace === 'book',
		reason: input.reason || '' // using an empty string here as fallback will help with prod-2.

	if (!params.blp && !params.reason) {
		if (!confirm) {
			return;

	Morebits.simpleWindow.setButtonsEnabled(false);
	Morebits.status.init(form);

	var talk_title = new mw.Title(mw.config.get('wgPageName')).getTalkPage.getPrefixedText;
	// Talk page templates for PROD-able discussions
	var blocking_templates = 'Template:Old XfD multi|Template:Old MfD|Template:Oldffdfull|' + // Common prior XfD talk page templates
		'Template:Oldpuffull|' + // Legacy prior XfD template
		'Template:Olddelrev|' + // Prior DRV template
		'Template:Old prod';
	var query = {
		'action': 'query',
		'titles': talk_title,
		'prop': 'templates',
		'tltemplates': blocking_templates

	var wikipedia_api = new Morebits.wiki.api;
	wikipedia_api.params = params;
	wikipedia_api.post;

Twinkle.addInitCallback;