text: import { SyncedCron } from 'meteor/littledata:synced-cron';
  
  import { settings } from '../../settings/server';
  import { Rooms } from '../../models/server';
  import { cleanRoomHistory } from '../../lib';
  
  let types = [];
  
  const oldest = new Date('0001-01-01T00:00:00Z');
  
  const maxTimes = {
  	c: 0,
  	p: 0,
  	d: 0,
  };
  
  const toDays = (d) => d * 1000 * 60 * 60 * 24;
  
  function job() {
  	const now = new Date();
  	const filesOnly = settings.get('RetentionPolicy_FilesOnly');
  	const excludePinned = settings.get('RetentionPolicy_DoNotPrunePinned');
  	const ignoreDiscussion = settings.get('RetentionPolicy_DoNotPruneDiscussion');
  	const ignoreThreads = settings.get('RetentionPolicy_DoNotPruneThreads');
  
  	// get all rooms with default values
  	types.forEach((type) => {
  		const maxAge = maxTimes[type] || 0;
  		const latest = new Date(now.getTime() - toDays(maxAge));
  
  		Rooms.find(
  			{
  				't': type,
  				'$or': [{ 'retention.enabled': { $eq: true } }, { 'retention.enabled': { $exists: false } }],
  				'retention.overrideGlobal': { $ne: true },
  			},
  			{ fields: { _id: 1 } },
  		).forEach(({ _id: rid }) => {
  			cleanRoomHistory({
  				rid,
  				latest,
  				oldest,
  				filesOnly,
  				excludePinned,
  				ignoreDiscussion,
  				ignoreThreads,
  			});
  		});
  	});
  
  	Rooms.find({
  		'retention.enabled': { $eq: true },
  		'retention.overrideGlobal': { $eq: true },
  		'retention.maxAge': { $gte: 0 },
  	}).forEach((room) => {
  		const { maxAge = 30, filesOnly, excludePinned, ignoreThreads } = room.retention;
  		const latest = new Date(now.getTime() - toDays(maxAge));
  		cleanRoomHistory({
  			rid: room._id,
  			latest,
  			oldest,
  			filesOnly,
  			excludePinned,
  			ignoreDiscussion,
  			ignoreThreads,
  		});
  	});
  }
  
  function getSchedule(precision) {
  	switch (precision) {
  		case '0':
  			return '*/30 * * * *'; // 30 minutes
  		case '1':
  			return '0 * * * *'; // hour
  		case '2':
  			return '0 */6 * * *'; // 6 hours
  		case '3':
  			return '0 0 * * *'; // day
  	}
  }
  
  const pruneCronName = 'Prune old messages by retention policy';
  
  function deployCron(precision) {
  	const schedule = (parser) => parser.cron(precision);
  
  	SyncedCron.remove(pruneCronName);
  	SyncedCron.add({
  		name: pruneCronName,
  		schedule,
  		job,
  	});
  }
  
  settings.watchMultiple(
  	[
  		'RetentionPolicy_Enabled',
  		'RetentionPolicy_AppliesToChannels',
  		'RetentionPolicy_AppliesToGroups',
  		'RetentionPolicy_AppliesToDMs',
  		'RetentionPolicy_MaxAge_Channels',
  		'RetentionPolicy_MaxAge_Groups',
  		'RetentionPolicy_MaxAge_DMs',
  		'RetentionPolicy_Advanced_Precision',
  		'RetentionPolicy_Advanced_Precision_Cron',
  		'RetentionPolicy_Precision',
  	],
  	function reloadPolicy() {
  		types = [];
  
  		if (!settings.get('RetentionPolicy_Enabled')) {
  			return SyncedCron.remove(pruneCronName);
  		}
  		if (settings.get('RetentionPolicy_AppliesToChannels')) {
  			types.push('c');
  		}
  
  		if (settings.get('RetentionPolicy_AppliesToGroups')) {
  			types.push('p');
  		}
  
  		if (settings.get('RetentionPolicy_AppliesToDMs')) {
  			types.push('d');
  		}
  
  		maxTimes.c = settings.get('RetentionPolicy_MaxAge_Channels');
  		maxTimes.p = settings.get('RetentionPolicy_MaxAge_Groups');
  		maxTimes.d = settings.get('RetentionPolicy_MaxAge_DMs');
  
  		const precision =
  			(settings.get('RetentionPolicy_Advanced_Precision') && settings.get('RetentionPolicy_Advanced_Precision_Cron')) ||
  			getSchedule(settings.get('RetentionPolicy_Precision'));
  
  		return deployCron(precision);
  	},
  );
  