const SET_READ_INTERVAL = 300;
const SET_ITEMS_TO_READ_DURATION = 100;
const SET_ITEM_TO_READ_DURATION = 1000;

const TITLE_UPDATE_INTERVAL = 1000;

// @todo: это по сути набросок универсального механизма прочитанности.
// Базовые вещи оставить здесь, добавить настройки, отнаследоваться в треках и личке.
// В более идеальном мире - сделать механизм прочтения универсальным от сервера до клиента,
// чтобы прочитанность ставилась через один метод для любых типов сообщений-треков.
// Сейчас этого ничего делать не стал, потому что личку надо перерабатывать - легко ломается.
function ReadTrackService(options) {
	this.lastItemId = 0;

	this.unreadCount = 0;
	this.attentionTimer = 0;
	this.onlineTimer = 0;
	this.itemsToRead = [];
	this.title = $('title').text();

  this.actorType = '';
	this.orderId = 0;
  this.dialogId = 0;
	this.opponentId = 0;

	this.itemIdPrefix = options.itemIdPrefix;

	var _self = this;

	$(document).ready(function () {
		_self.setEvents();
	});

	$(window).load(function () {
		_self.setUnreadPageCount();
		if (_self.unreadCount > 0) {
			_self.setTitleAttention();
		}
	});
}

/**
 * Инициализация.
 *
 * @param options
 */
ReadTrackService.prototype.init = function (options) {
  this.actorType = options.actorType;
	this.orderId = options.orderId;
  this.dialogId = options.dialogId;
	this.opponentId = options.opponentId;
};

/**
 * Установить уведомление в заголовке окна браузера о количестве новых сообщений
 * @private
 */
ReadTrackService.prototype.setTitleAttention = function () {
	var _self = this;

	if (_self.attentionTimer) {
		return;
	}

	var i = 0;
	_self.attentionTimer = setInterval(function () {
		if (i % 2) {
			_self.updateTitleUnreadCount();
		}
		else {
			$('title').text('*** ' + _self.title);
		}
		i++;
	}, TITLE_UPDATE_INTERVAL);
};

/**
 * Убрать уведомление в заголовке окна браузера о количестве новых сообщений
 * @private
 */
ReadTrackService.prototype.clearTitleAttention = function () {
	var _self = this;
	if (_self.attentionTimer) {
		clearInterval(_self.attentionTimer);
		_self.attentionTimer = 0;
	}
	_self.updateTitleUnreadCount();
};

/**
 * Посчитать количество непрочитанных сообщений
 */
ReadTrackService.prototype.setUnreadPageCount = function () {
	this.unreadCount = $('.unread:not(.out)').length;
};

/**
 * Обновить количество непрочитанных сообщений в заголовке окна браузера
 */
ReadTrackService.prototype.updateTitleUnreadCount = function () {
	var newTitle = this.title;

	this.setUnreadPageCount();

	if (this.unreadCount) {
		newTitle = '[' + this.unreadCount + '] ' + newTitle;
	}

	$('title').text(newTitle);
	if (!this.unreadCount) {
		clearInterval(this.attentionTimer);
	}
};

/**
 * Название дикое, потому что метод должен собрать сообщения для прочтения
 * с задержкой собирания для каждого отдельного сообщения.
 */
ReadTrackService.prototype.setUnreadItemTimeoutsToGarbage = function () {
	var _self = this;

	if (_self.unreadCount === 0) {
		//return;
	}

	_self.clearTitleAttention();

	$('.unread:not(.out)').each(function() {
		var $item = $(this);

    /*
		if ((_self.orderId > 0 && $item.is(':within-viewport-bottom'))
        || (_self.dialogId > 0
            && ((!IS_MOBILE && $('#msgresults').prop('scrollHeight') <= ($('#msgresults').scrollTop() + $('#msgresults').prop('clientWidth')))
                || (IS_MOBILE && ($('#msgresults').prop('clientHeight') - $('#msgresults').prop('offsetTop') - (window.innerHeight - $('#block_message').prop('clientHeight'))) <= $(document).scrollTop())
               )
            )
       ) {
    */
		if ($item.is(':within-viewport-bottom')){
      if ($item.data('readTimeout')) {
    		return;
    	}

    	$item.data('readTimeout', setTimeout(function () {
    		_self.itemsToRead.push(_self.getItemId($item));
    	}, SET_ITEM_TO_READ_DURATION));
		}
		else {
			_self._resetItemTimer($item);
		}
	});
};

/**
 * Отмечает сообщение на странице прочитанным.
 *
 * @param $item
 * @private
 */
ReadTrackService.prototype._setReadItem = function($item) {
	$item.removeClass('unread');
};

/**
 * Отметить исходящие сообщения прочитанными
 *
 * @param {Array} itemIds id прочитанных сообщений
 * @private
 */
ReadTrackService.prototype._setReadOutItems = function (itemIds) {
	var _self = this;

	if (itemIds) {
		itemIds = itemIds.map(function (val) {
			return val ^ 0;
		});
	}

	$('.unread.out').each(function () {
		var $item = $(this);
		if (!itemIds || itemIds.indexOf(_self.getItemId($item)) !== -1) {
			$item.find('.message-icons').hide();
			_self._setReadItem($item);
		}
	});
};

/**
 * Пометить сообщения прочитанными.
 *
 * @param response
 * @private
 */
ReadTrackService.prototype._onReadItems = function (response) {
	if (this.opponentId != response.fromUserId) {
		return;
	}

	this._setReadOutItems(response.itemIds);
};

/**
 * Сбрасывает таймер задержки прочтения для отдельного сообщения.
 *
 * @param $item
 * @private
 */
ReadTrackService.prototype._resetItemTimer = function($item) {
	clearTimeout($item.data('readTimeout') ^ 0);
	$item.data('readTimeout', 0);
};

/**
 * Отправить запрос на чтение сообщений
 * @private
 */
ReadTrackService.prototype.sendReadItems = function () {
	var params = {
		itemIds: this.itemsToRead,
		orderId: this.orderId,
    dialogId: this.dialogId
	};

  Api.request('track_read', params, function () { });

  this.itemsToRead = [];
};

/**
 * Возвращает id сообщения.
 *
 * @param $item
 * @returns {number}
 */
ReadTrackService.prototype.getItemId = function($item) {
	return $item.data('track-id') ^ 0;
};

/**
 * Устанавливает обработчики событий.
 */
ReadTrackService.prototype.setEvents = function () {
	var _self = this;

	PullModule.on(PULL_EVENT_READ_TRACK, function(response) {
		_self._onReadItems(response);
	});

	$('.js-alt-send').on('focus click', function () {
		_self.clearTitleAttention();
	});

	var throttleSetMessagesToRead = Utils.throttle(function() {
		_self.setUnreadItemTimeoutsToGarbage();
	}, SET_ITEMS_TO_READ_DURATION, false, true);

	throttleSetMessagesToRead();

	//((IS_MOBILE || IS_ORDER_PAGE > 0) ? $(window) : $('#msgresults')).bind("scroll focus", function () {
  $(window).bind("scroll focus", function () {
		if (Utils.isActiveWindow()) {
			if ($('.unread:not(.out)').length > 0) {
				Utils.throttle(function() {
					_self.clearTitleAttention();
				}, SET_ITEMS_TO_READ_DURATION);
			}

			_self.clearTitleAttention();
			throttleSetMessagesToRead();
		}
	});

	$(document).on("click", function () {
		_self.clearTitleAttention();
	});

	setInterval(function () {
		if (_self.actorType == 'admin' || !_self.itemsToRead.length || !Utils.isActiveWindow()) {
			return;
		}

		var maxId = Math.max.apply(null, _self.itemsToRead);
		$('.unread:not(.out)').each(function () {
			var $item = $(this);
			var itemId = _self.getItemId($item);
			if (itemId <= maxId) {
				_self._setReadItem($item);
				_self._resetItemTimer($item);
			}
		});

		$.each(_self.itemsToRead, function(i, itemId) {
			_self._setReadItem($(_self.itemIdPrefix + itemId));
		});

		_self.setUnreadPageCount();
		_self.updateTitleUnreadCount();
		_self.sendReadItems();

		_self.itemsToRead = [];
	}, SET_READ_INTERVAL);
};
