"use strict";

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

let currentSeason = require('./settings/current-season');

let customSettings = ['currentSeason'];

module.exports = Object.assign({

	init() {
		this.cache = {};
		this.db = blackout.db;
		this.dynamo = blackout.dynamo;
	},

	currentLock: 0,

	get(setting, callback) {
		var _this = this;

		return _asyncToGenerator(function* () {

			let checkCachesOnly = false,
			    alreadyLocked;
			if (typeof setting === 'object') {
				if ('checkCachesOnly' in setting) {
					checkCachesOnly = setting.checkCachesOnly;
				}
				alreadyLocked = setting.lock;
				setting = setting.setting;
			}

			let settingObject = {
				table: 'Settings',
				Id: setting
			};

			// Check local cache
			if (setting in _this.cache) {

				console.log(`LOCALCACHE - Settings -> ${setting}`);
				callback(null, _this.cache[setting]);
			} else {

				let lock;
				if (!alreadyLocked) {

					// Lock for this setting
					let lockKey = blackout.makeItemLockKey('Settings', settingObject);
					_this.currentLock++;
					lock = yield blackout.waitForLockAsync(lockKey, 1000, true);

					if (!lock) {
						/**
       * Just continue if there's no lock... this just helps us
       * so that we don't have may async calls getting the same
       * setting, e.g. getSeasonAndDay during player creation
       */
					}
				}

				// Check local cache again after locking, just in case another async function has added data
				if (setting in _this.cache) {

					console.log(`LOCALCACHE2 - Settings -> ${setting}`);
					yield blackout.unlockAsync(lock);
					callback(null, _this.cache[setting]);
				} else {

					let params = {
						table: 'Settings',
						id: setting,
						cacheOnly: true
					};

					// Get from cache
					let item = yield _this.db.getItemAsync(params);

					if (item && 'Value' in item && item.Value !== undefined) {

						yield blackout.unlockAsync(lock);
						callback(null, item.Value);
					} else if (checkCachesOnly) {

						yield blackout.unlockAsync(lock);
						callback(null, null);
					} else {

						if (customSettings.includes(setting)) {

							switch (setting) {

								case 'currentSeason':

									_this.getCurrentSeason((() => {
										var _ref = _asyncToGenerator(function* (err, val) {
											yield _this.updateLocalCacheAsync(setting, val);
											yield blackout.unlockAsync(lock);
											callback(null, val);
										});

										return function (_x, _x2) {
											return _ref.apply(this, arguments);
										};
									})());
									break;

								default:

									blackout.errorInternal(new Error('Custom setting getter not found for setting: ' + setting));

							}
						} else {

							// Get from DynamoDB
							params.cacheOnly = false;

							let item = yield _this.db.getItemAsync(params);
							if (item && 'Value' in item && item.Value !== undefined) {
								yield _this.updateLocalCacheAsync(setting, item.Value);
								yield blackout.unlockAsync(lock);
								callback(null, item.Value);
							} else {
								yield blackout.unlockAsync(lock);
								callback(null, null);
							}
						}
					}
				}
			}
		})();
	},

	getFromCache(setting, lock, callback) {
		if (!callback && typeof lock === 'function') {
			callback = lock;
			lock = null;
		}
		this.get({ setting: setting, checkCachesOnly: true, lock: lock }, callback);
	},

	set(setting, value, callback) {
		var _this2 = this;

		return _asyncToGenerator(function* () {

			if (!customSettings.includes(setting)) {

				let params = {
					table: 'Settings',
					patch: {
						Id: setting,
						Value: value
					}
				};

				yield _this2.db.updateItemAsync(params);
				_this2.updateLocalCache(setting, value, callback);
			} else {
				blackout.errorInternal(new Error('Tried to set custom setting: ' + setting + '. Custom settings are derived from some other input and cannot be set in this way.'));
			}
		})();
	},

	del(setting, callback) {
		var _this3 = this;

		return _asyncToGenerator(function* () {

			if (!customSettings.includes(setting)) {

				let params = {
					table: 'Settings',
					item: {
						Id: setting
					}
				};

				yield _this3.db.deleteItemAsync(params);
				delete _this3.cache[setting];
				let err = null;
				callback(err);
			} else {
				blackout.errorInternal(new Error('Tried to delete custom setting: ' + setting + '. Custom settings are derived from some other input and cannot be deleted in this way.'));
			}
		})();
	},

	delete(setting, callback) {
		this.del(setting, callback);
	},

	// --------------------------------------------- Internal functions

	updateLocalCache(setting, value, callback) {

		// Update local cache
		this.cache[setting] = value;
		callback(null, value);
	},

	updateCustomCache(setting, value, callback) {
		var _this4 = this;

		return _asyncToGenerator(function* () {

			let params = {
				table: 'Settings',
				item: {
					Id: setting,
					Value: value
				}
			};

			yield _this4.db.updateItemInCacheOnlyAsync(params);
			_this4.updateLocalCache(setting, value, callback);
		})();
	}

}, currentSeason);
//# sourceMappingURL=settings.js.map