"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.listItemRepository = void 0;

var _dbconfig = require("../dbconfig");

var _repository = require("./repository");

function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }

function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }

var _addOrRemoveListItemFactory = /*#__PURE__*/new WeakSet();

class ListItemRepository extends (0, _repository.repository)({
  tableName: 'listItem',
  primaryColumnName: 'id'
}) {
  constructor(..._args) {
    super(..._args);

    _classPrivateMethodInitSpec(this, _addOrRemoveListItemFactory);

    _defineProperty(this, "addItem", _classPrivateMethodGet(this, _addOrRemoveListItemFactory, _addOrRemoveListItemFactory2).call(this, async (trx, args) => {
      const {
        mediaItemId,
        seasonId,
        episodeId,
        listId
      } = args;

      if (mediaItemId && seasonId) {
        const season = await trx('season').where('tvShowId', mediaItemId).where('id', seasonId).first();

        if (!season) {
          return false;
        }
      }

      if (mediaItemId && episodeId) {
        const episode = await trx('episode').where('tvShowId', mediaItemId).where('id', episodeId).first();

        if (!episode) {
          return false;
        }
      }

      const existingItems = await trx('listItem').where({
        listId: listId,
        mediaItemId: mediaItemId,
        seasonId: episodeId == undefined ? seasonId || null : null,
        episodeId: episodeId || null
      });

      if (existingItems.length > 0) {
        return false;
      }

      await trx('listItem').insert({
        listId: listId,
        mediaItemId: mediaItemId,
        seasonId: episodeId == undefined ? seasonId || null : null,
        episodeId: episodeId || null,
        addedAt: new Date().getTime(),
        rank: trx.raw(`(${trx('listItem').count().where('listId', listId).toQuery()})`)
      });
      return true;
    }));

    _defineProperty(this, "removeItem", _classPrivateMethodGet(this, _addOrRemoveListItemFactory, _addOrRemoveListItemFactory2).call(this, async (trx, args) => {
      const {
        mediaItemId,
        seasonId,
        episodeId,
        listId
      } = args;
      const listItem = await trx('listItem').where({
        mediaItemId: mediaItemId,
        seasonId: seasonId || null,
        episodeId: episodeId || null,
        listId: listId
      }).first();

      if (listItem) {
        await trx('listItem').delete().where('id', listItem.id); // update `listItem` set `rank` = `rank` - 1 where `rank` > `listItem`.`rank`
        // will fail on SQLite when deleted item is not last by rowId due to
        // UNIQUE constraint on listId and rank

        const listItems = await trx('listItem').where('rank', '>', listItem.rank).where('listId', listId).orderBy('rank', 'asc');

        for (const item of listItems) {
          await trx('listItem').update('rank', item.rank - 1).where('id', item.id);
        }
      }

      return true;
    }));
  }

}

function _addOrRemoveListItemFactory2(fn) {
  return async args => {
    const {
      userId,
      listId,
      watchlist,
      mediaItemId,
      seasonId,
      episodeId
    } = {
      listId: undefined,
      watchlist: undefined,
      ...args
    };

    if (listId != undefined && watchlist != undefined || listId == undefined && watchlist == undefined) {
      throw new Error('only one of listId and addToWatchlist arguments should be provided');
    }

    return await _dbconfig.Database.knex.transaction(async trx => {
      const list = await trx('list').where(listId != undefined ? {
        id: listId
      } : {
        isWatchlist: true,
        userId: userId
      }).first();

      if (!list || list.userId !== userId && list.privacy === 'private') {
        return false;
      }

      return fn(trx, {
        mediaItemId,
        seasonId,
        episodeId,
        userId,
        listId: list.id
      });
    });
  };
}

const listItemRepository = new ListItemRepository();
exports.listItemRepository = listItemRepository;
//# sourceMappingURL=listItemRepository.js.map