text: import { View } from 'framework/views/view';
  import { Events } from 'framework/events';
  import { SearchResultCollection } from 'collections/search-result-collection';
  import { DragDropInfo } from 'comp/app/drag-drop-info';
  import { Alerts } from 'comp/ui/alerts';
  import { AppSettingsModel } from 'models/app-settings-model';
  import { EntryPresenter } from 'presenters/entry-presenter';
  import { StringFormat } from 'util/formatting/string-format';
  import { Locale } from 'util/locale';
  import { Resizable } from 'framework/views/resizable';
  import { Scrollable } from 'framework/views/scrollable';
  import { DropdownView } from 'views/dropdown-view';
  import { ListSearchView } from 'views/list-search-view';
  import throttle from 'lodash/throttle';
  import template from 'templates/list.hbs';
  import emptyTemplate from 'templates/list-empty.hbs';
  
  class ListView extends View {
      parent = '.app__list';
  
      template = template;
  
      emptyTemplate = emptyTemplate;
  
      events = {
          'click': 'click',
          'click .list__table-options': 'tableOptionsClick',
          'dragstart .list__item': 'itemDragStart'
      };
  
      minWidth = 200;
      minHeight = 200;
      maxWidth = 500;
      maxHeight = 500;
  
      itemsEl = null;
  
      tableColumns = [
          { val: 'title', name: 'title', enabled: true },
          { val: 'user', name: 'user', enabled: true },
          { val: 'url', name: 'website', enabled: true },
          { val: 'tags', name: 'tags', enabled: true },
          { val: 'notes', name: 'notes', enabled: true },
          { val: 'groupName', name: 'group', enabled: false },
          { val: 'fileName', name: 'file', enabled: false }
      ];
  
      constructor(model, options) {
          super(model, options);
  
          this.initScroll();
          this.views.search = new ListSearchView(this.model);
  
          this.listenTo(this.views.search, 'select-prev', this.selectPrev);
          this.listenTo(this.views.search, 'select-next', this.selectNext);
          this.listenTo(this.views.search, 'create-entry', this.createEntry);
          this.listenTo(this.views.search, 'create-group', this.createGroup);
          this.listenTo(this.views.search, 'create-template', this.createTemplate);
          this.listenTo(this, 'show', this.viewShown);
          this.listenTo(this, 'hide', this.viewHidden);
          this.listenTo(this, 'view-resize', this.viewResized);
          this.listenTo(Events, 'filter', this.filterChanged);
          this.listenTo(Events, 'entry-updated', this.entryUpdated);
          this.listenTo(Events, 'set-locale', this.render);
  
          this.listenTo(this.model.settings, 'change:tableView', this.setTableView);
  
          this.readTableColumnsEnabled();
  
          this.items = new SearchResultCollection();
      }
  
      render() {
          if (!this.itemsEl) {
              super.render();
              this.itemsEl = this.$el.find('.list__items>.scroller');
              this.views.search.render();
              this.setTableView();
  
              this.createScroll({
                  root: this.$el.find('.list__items')[0],
                  scroller: this.$el.find('.scroller')[0],
                  bar: this.$el.find('.scroller__bar')[0]
              });
          }
          if (this.items.length) {
              const itemTemplate = this.getItemTemplate();
              const itemsTemplate = this.getItemsTemplate();
              const noColor = AppSettingsModel.colorfulIcons ? '' : 'grayscale';
              const presenter = new EntryPresenter(
                  this.getDescField(),
                  noColor,
                  this.model.activeEntryId
              );
              const columns = {};
              this.tableColumns.forEach(col => {
                  if (col.enabled) {
                      columns[col.val] = true;
                  }
              });
              presenter.columns = columns;
              let itemsHtml = '';
              this.items.forEach(item => {
                  presenter.present(item);
                  itemsHtml += itemTemplate(presenter);
              }, this);
              const html = itemsTemplate({ items: itemsHtml, columns: this.tableColumns });
              this.itemsEl.html(html);
          } else {
              this.itemsEl.html(this.emptyTemplate());
          }
          this.pageResized();
      }
  
      getItemsTemplate() {
          if (this.model.settings.tableView) {
              return require('templates/list-table.hbs');
          } else {
              return this.renderPlainItems;
          }
      }
  
      renderPlainItems(itemsHtml) {
          return itemsHtml.items;
      }
  
      getItemTemplate() {
          if (this.model.settings.tableView) {
              return require('templates/list-item-table.hbs');
          } else {
              return require('templates/list-item-short.hbs');
          }
      }
  
      getDescField() {
          return this.model.sort.replace('-', '');
      }
  
      click(e) {
          const listItemEl = e.target.closest('.list__item');
          if (!listItemEl) {
              return;
          }
          const id = listItemEl.id;
          const item = this.items.get(id);
          if (!item.active) {
              this.selectItem(item);
          }
          Events.emit('toggle-details', true);
      }
  
      selectPrev() {
          const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
          if (ix > 0) {
              this.selectItem(this.items[ix - 1]);
          }
      }
  
      selectNext() {
          const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
          if (ix < this.items.length - 1) {
              this.selectItem(this.items[ix + 1]);
          }
      }
  
      createEntry(arg) {
          const newEntry = this.model.createNewEntry(arg);
          this.items.unshift(newEntry);
          this.render();
          this.selectItem(newEntry);
          Events.emit('toggle-details', true);
      }
  
      createGroup() {
          const newGroup = this.model.createNewGroup();
          Events.emit('edit-group', newGroup);
      }
  
      createTemplate() {
          if (!this.model.settings.templateHelpShown) {
              Alerts.yesno({
                  icon: 'sticky-note-o',
                  header: Locale.listAddTemplateHeader,
                  body:
                      Locale.listAddTemplateBody1.replace('{}', '<i class="fa fa-plus"></i>') +
                      '<br/>' +
                      Locale.listAddTemplateBody2.replace('{}', 'Templates'),
                  buttons: [Alerts.buttons.ok, Alerts.buttons.cancel],
                  success: () => {
                      this.model.settings.templateHelpShown = true;
                      this.createTemplate();
                  }
              });
              return;
          }
          const templateEntry = this.model.createNewTemplateEntry();
          this.items.unshift(templateEntry);
          this.render();
          this.selectItem(templateEntry);
      }
  
      selectItem(item) {
          this.model.activeEntryId = item.id;
          Events.emit('entry-selected', item);
          this.itemsEl.find('.list__item--active').removeClass('list__item--active');
          const itemEl = document.getElementById(item.id);
          itemEl.classList.add('list__item--active');
          const listEl = this.itemsEl[0];
          const itemRect = itemEl.getBoundingClientRect();
          const listRect = listEl.getBoundingClientRect();
          if (itemRect.top < listRect.top) {
              listEl.scrollTop += itemRect.top - listRect.top;
          } else if (itemRect.bottom > listRect.bottom) {
              listEl.scrollTop += itemRect.bottom - listRect.bottom;
          }
      }
  
      viewShown() {
          this.views.search.show();
      }
  
      viewHidden() {
          this.views.search.hide();
      }
  
      setTableView() {
          const isTable = this.model.settings.tableView;
          this.dragView.setCoord(isTable ? 'y' : 'x');
          this.setDefaultSize();
      }
  
      setDefaultSize() {
          this.setSize(this.model.settings.listViewWidth);
      }
  
      setSize(size) {
          this.$el.css({ width: 'auto', height: 'auto' });
          if (size) {
              this.$el.css('flex', '0 0 ' + size + 'px');
          } else {
              this.$el.css('flex', '');
          }
      }
  
      viewResized(size) {
          this.setSize(size);
          this.throttleSetViewSizeSetting(size);
      }
  
      throttleSetViewSizeSetting = throttle(size => {
          AppSettingsModel.listViewWidth = size;
      }, 1000);
  
      filterChanged(filter) {
          this.items = filter.entries;
          this.render();
      }
  
      entryUpdated() {
          const scrollTop = this.itemsEl[0].scrollTop;
          this.render();
          this.itemsEl[0].scrollTop = scrollTop;
      }
  
      itemDragStart(e) {
          e.stopPropagation();
          const id = $(e.target)
              .closest('.list__item')
              .attr('id');
          e.dataTransfer.setData('text/entry', id);
          e.dataTransfer.effectAllowed = 'move';
          DragDropInfo.dragObject = this.items.get(id);
      }
  
      tableOptionsClick(e) {
          e.stopImmediatePropagation();
          if (this.views.optionsDropdown) {
              this.hideOptionsDropdown();
              return;
          }
          const view = new DropdownView();
          this.listenTo(view, 'cancel', this.hideOptionsDropdown);
          this.listenTo(view, 'select', this.optionsDropdownSelect);
          const targetElRect = this.$el.find('.list__table-options')[0].getBoundingClientRect();
          const options = this.tableColumns.map(col => ({
              value: col.val,
              icon: col.enabled ? 'check-square-o' : 'square-o',
              text: StringFormat.capFirst(Locale[col.name])
          }));
          view.render({
              position: {
                  top: targetElRect.bottom,
                  left: targetElRect.left
              },
              options
          });
          this.views.optionsDropdown = view;
      }
  
      hideOptionsDropdown() {
          if (this.views.optionsDropdown) {
              this.views.optionsDropdown.remove();
              delete this.views.optionsDropdown;
          }
      }
  
      optionsDropdownSelect(e) {
          const col = this.tableColumns.find(c => c.val === e.item);
          col.enabled = !col.enabled;
          e.el.find('i:first').toggleClass('fa-check-square-o fa-square-o');
          this.render();
          this.saveTableColumnsEnabled();
      }
  
      readTableColumnsEnabled() {
          const tableViewColumns = AppSettingsModel.tableViewColumns;
          if (tableViewColumns && tableViewColumns.length) {
              this.tableColumns.forEach(col => {
                  col.enabled = tableViewColumns.indexOf(col.name) >= 0;
              });
          }
      }
  
      saveTableColumnsEnabled() {
          const tableViewColumns = this.tableColumns
              .filter(column => column.enabled)
              .map(column => column.name);
          AppSettingsModel.tableViewColumns = tableViewColumns;
      }
  }
  
  Object.assign(ListView.prototype, Resizable);
  Object.assign(ListView.prototype, Scrollable);
  
  export { ListView };
  