text: const $ = require('jquery');
  const moment = require('moment');
  const CoreView = require('backbone/core-view');
  const UserNotificationsCollection = require('./notifications-collection');
  const NotificationsDropdown = require('./dropdown-view');
  const template = require('./templates/user-notifications.tpl');
  const dropdownTemplate = require('./templates/dropdown.tpl');
  const LocalStorage = require('../../../helpers/local-storage');
  const checkAndBuildOpts = require('../../../../builder/helpers/required-opts');
  
  const TEMPLATES = {
    tryTrial: require('./templates/try-trial.tpl'),
    limitsExceeded: require('./templates/limits-exceeded.tpl'),
    closeLimits: require('./templates/close-limits.tpl'),
    upgradedMessage: require('./templates/upgraded-message.tpl'),
    trialEndsSoon: require('./templates/trial-ends-soon.tpl')
  };
  
  const REQUIRED_OPTS = [
    'configModel',
    'user'
  ];
  
  /**
   *  User notifactions view used to show alerts from the application
   *
   *  In storage we will check these attributes, managed by a collection:
   *
   *  try_trial       -> trial_end_at is null && user is not paid user
   *  limits_exceeded -> check table quota size
   *  close_limits    -> check table quota size < 80%
   *  upgraded        -> check upgraded_at less than one week
   *  trial_ends_soon -> trial_end_at is not null and it is close to be finished
   *  new_dashboard   -> new dashboard
   *  notification    -> check notification
   *
   */
  
  module.exports = CoreView.extend({
  
    attributes: {
      href: '#/notifications'
    },
  
    tagName: 'a',
    className: 'UserNotifications',
  
    events: {
      'click': '_openNotifications'
    },
  
    initialize: function (options) {
      checkAndBuildOpts(options, REQUIRED_OPTS, this);
  
      this.localStorage = new LocalStorage();
      this.collection = new UserNotificationsCollection({
        configModel: options.configModel
      });
      this.collection.reset(this._generateCollection(), {
        userId: this._user.get('id'),
        apiKey: this._user.get('api_key'),
        silent: true
      });
  
      this._initBinds();
    },
  
    render: function () {
      var notificationsCount = this.collection.filter(item => !item.get('opened')).length;
  
      this.$el.html(
        template({
          notificationsCount: notificationsCount
        })
      );
  
      this.$el.toggleClass('has--alerts', notificationsCount > 0);
  
      return this;
    },
  
    _initBinds: function () {
      this._user.bind('change', this._onUserChange, this);
      this.collection.bind('reset', this.render, this);
      this.collection.bind('remove', this.render, this);
      this.add_related_model(this._user);
      this.add_related_model(this.collection);
    },
  
    _onUserChange: function () {
      // When api is ready, we will make a valid fetch :)
      this.collection.reset(this._generateCollection(), {
        userId: this._user.get('id'),
        apiKey: this._user.get('api_key')
      });
      this.render();
    },
  
    // This method will check notifications and create a collection with them
    // Also it will check if those have been opened or not with Local Storage.
    _generateCollection: function () {
      var arr = [];
      var data = {}; // data
      var userUrl = this._user.viewUrl();
      var comHosted = this._configModel.get('cartodb_com_hosted');
  
      data.isInsideOrg = this._user.isInsideOrg();
      data.isOrgOwner = this._user.isOrgOwner();
      data.accountType = this._user.get('account_type').toLowerCase();
      data.remainingQuota = this._user.get('remaining_byte_quota');
      data.publicProfileUrl = userUrl.publicProfile();
      data.bytesQuota = this._user.get('quota_in_bytes');
      data.userType = 'regular';
      data.upgradeUrl = window.upgrade_url || '';
      data.upgradeContactEmail = this._user.upgradeContactEmail();
      data.trialEnd = this._user.get('trial_ends_at') && moment(this._user.get('trial_ends_at')).format('YYYY-MM-DD');
      data.userName = this._user.get('name') || this._user.get('username');
  
      // Get user type
      if (data.isInsideOrg && !data.isOrgOwner) {
        data.userType = 'org';
      } else if (data.isOrgOwner) {
        data.userType = 'admin';
      } else if (data.accountType === 'internal' || data.accountType === 'partner' || data.accountType === 'ambassador') {
        data.userType = 'internal';
      }
  
      // try_trial -> trial_end_at is null && user is not paid user
      if (!comHosted && !data.isInsideOrg && data.accountType === 'free' && this._user.get('table_count') > 0) {
        arr.push({
          iconFont: 'CDB-IconFont-gift',
          severity: 'NotificationsDropdown-itemIcon--positive',
          type: 'try_trial',
          msg: TEMPLATES.tryTrial(data),
          opened: this.localStorage.get('notification.try_trial')
        });
      } else {
        this.localStorage.remove('notification.try_trial');
      }
  
      // limits_exceeded -> check table quota size
      if (!comHosted && data.bytesQuota > 0 && data.remainingQuota <= 0) {
        arr.push({
          iconFont: 'CDB-IconFont-barometer',
          severity: 'NotificationsDropdown-itemIcon--negative',
          type: 'limits_exceeded',
          msg: TEMPLATES.limitsExceeded(data),
          opened: this.localStorage.get('notification.limits_exceeded')
        });
      } else {
        this.localStorage.remove('notification.limits_exceeded');
      }
  
      // close_limits -> check table quota size < 80%
      if (!comHosted && data.bytesQuota > 0 && ((data.remainingQuota * 100) / data.bytesQuota) < 20) {
        arr.push({
          iconFont: 'CDB-IconFont-barometer',
          severity: 'NotificationsDropdown-itemIcon--alert',
          type: 'close_limits',
          msg: TEMPLATES.closeLimits(data),
          opened: this.localStorage.get('notification.close_limits')
        });
      } else {
        this.localStorage.remove('notification.close_limits');
      }
  
      // upgraded -> check upgraded_at less than ... one week?
      if (!comHosted && this._user.get('show_upgraded_message')) {
        arr.push({
          iconFont: 'CDB-IconFont-heartFill',
          severity: 'NotificationsDropdown-itemIcon--positive',
          type: 'upgraded_message',
          msg: TEMPLATES.upgradedMessage(data),
          opened: this.localStorage.get('notification.upgraded_message')
        });
      } else {
        this.localStorage.remove('notification.upgraded_message');
      }
  
      // trial_ends_soon -> show_trial_reminder flag
      if (this._user.get('show_trial_reminder')) {
        arr.push({
          iconFont: 'CDB-IconFont-clock',
          severity: 'NotificationsDropdown-itemIcon--alert',
          type: 'trial_ends_soon',
          msg: TEMPLATES.trialEndsSoon(data),
          opened: this.localStorage.get('notification.trial_ends_soon')
        });
      } else {
        this.localStorage.remove('notification.trial_ends_soon');
      }
  
      const organizationNotifications = window.organization_notifications || this.options.organizationNotifications;
  
      if (organizationNotifications) {
        for (var n = 0; n < organizationNotifications.length; n++) {
          var notification = organizationNotifications[n];
          var icon = notification.icon ? ('CDB-IconFont-' + notification.icon) : 'CDB-IconFont-alert';
  
          arr.push({
            iconFont: icon,
            severity: 'NotificationsDropdown-itemIcon--alert',
            id: notification.id,
            msg: notification.html_body,
            read_at: notification.read_at,
            type: 'org_notification'
          });
        }
      }
  
      return arr;
    },
  
    _openNotifications: function (event) {
      if (event) this.killEvent(event);
  
      if (this.notification) {
        this.notification.hide();
        delete this.notification;
        return this;
      }
  
      var view = this.notification = new NotificationsDropdown({
        target: this.$el,
        collection: this.collection,
        horizontal_offset: 5,
        vertical_offset: -5,
        template: dropdownTemplate
      });
  
      $(view.options.target).unbind('click', view._handleClick);
      this._closeAnyOtherOpenDialogs();
  
      view.on('onDropdownHidden', () => this._onDropdownHidden(view));
  
      view.render();
      view.open();
  
      this.addView(view);
    },
  
    _onDropdownHidden: function (view) {
      // All notifications have been seen, opened -> true
      this.collection.each(notification => {
        const notificationType = notification.get('type');
  
        if (notificationType === 'org_notification') {
          notification.markAsRead();
        } else if (notificationType) {
          notification.set('opened', true);
          this.localStorage.set({
            [`notification.${notificationType}`]: true
          });
        }
      });
  
      // Clean collection because all notifications should
      // removed from the collection
      this.collection.reset();
  
      // Clean dropdown
      view.clean();
      // Remove it from subviews
      this.removeView(view);
      // Remove count
      this.$el.removeClass('has--alerts');
      // No local notification set
      delete this.notification;
    },
  
    _closeAnyOtherOpenDialogs: function () {
      // cdb.god.trigger("closeDialogs"); TODO: handle event
    }
  });
  