/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

 foam.CLASS({
  package: 'foam.u2.view',
  name: 'ScrollTableView',
  extends: 'foam.u2.Element',

  requires: [
    'foam.dao.FnSink',
    'foam.graphics.ScrollCView',
    'foam.mlang.sink.Count',
    'foam.u2.view.TableView'
  ],

  css: `
    ^ {
      display: flex;
    }
  `,

  constants: [
    {
      type: 'Integer',
      name: 'TABLE_HEAD_HEIGHT',
      value: 40
    }
  ],

  properties: [
    {
      class: 'foam.dao.DAOProperty',
      name: 'data'
    },
    {
      class: 'Int',
      name: 'limit',
      value: 18,
      // TODO make this a funciton of the height.
    },
    {
      class: 'Int',
      name: 'skip',
    },
    {
      class: 'foam.dao.DAOProperty',
      name: 'scrolledDAO',
      expression: function(data, limit, skip) {
        return data && data.limit(limit).skip(skip);
      },
    },
    'columns',
    {
      class: 'FObjectArray',
      of: 'foam.core.Action',
      name: 'contextMenuActions'
    },
    {
      class: 'Int',
      name: 'daoCount'
    },
    'selection',
    {
      class: 'Boolean',
      name: 'editColumnsEnabled',
      documentation: `
        Set to true if users should be allowed to choose which columns to use.
      `,
      value: true
    },
    {
      class: 'Int',
      name: 'rowHeight',
      documentation: 'The height of one row of the table in px.',
      value: 48
    },
    {
      class: 'Boolean',
      name: 'fitInScreen',
      documentation: `
        If true, the table height will be dynamically set such that the table
        will not overflow off of the bottom of the page.
      `,
      value: false
    },
    {
      name: 'table_',
      documentation: `
        A reference to the table element we use in the fitInScreen calculations.
      `
    },
    {
      class: 'Int',
      name: 'accumulator',
      documentation: 'Used internally to mimic native scrolling speed.',
      adapt: function(_, v) {
        return v % this.rowHeight;
      }
    }
  ],

  methods: [
    function init() {
      this.onDetach(this.data$proxy.listen(this.FnSink.create({fn:this.onDAOUpdate})));
      this.onDAOUpdate();
    },

    function initE() {
      this.
        start().
          addClass(this.myClass()).
          on('wheel', this.onWheel).
          tag(this.TableView, {
            data$: this.scrolledDAO$,
            columns: this.columns,
            contextMenuActions: this.contextMenuActions,
            selection$: this.selection$,
            editColumnsEnabled: this.editColumnsEnabled
          }, this.table_$).
          start().
            show(this.daoCount$.map((count) => count >= this.limit)).
            add(this.slot(function(limit) {
              return this.ScrollCView.create({
                value$: this.skip$,
                extent$: this.limit$,
                height: this.rowHeight * limit + this.TABLE_HEAD_HEIGHT,
                width: 12,
                size$: this.daoCount$,
              });
            })).
          end().
        end();

      if ( this.fitInScreen ) {
        this.onload.sub(this.updateTableHeight);
        window.addEventListener('resize', this.updateTableHeight);
        this.onDetach(() => {
          window.removeEventListener('resize', this.updateTableHeight);
        });
      }
    }
  ],

  listeners: [
    {
      name: 'onWheel',
      code: function(e) {
        var negative = e.deltaY < 0;
        var rows = Math.floor(Math.abs(this.accumulator + e.deltaY) / this.rowHeight);
        this.accumulator += e.deltaY;
        this.skip = Math.max(0, this.skip + (negative ? -rows : rows));
        if ( e.deltaY !== 0 ) e.preventDefault();
      }
    },
    {
      // TODO: Avoid onDAOUpdate approaches.
      name: 'onDAOUpdate',
      isFramed: true,
      code: function() {
        var self = this;
        this.data$proxy.select(this.Count.create()).then(function(s) {
          self.daoCount = s.value;
        })
      }
    },
    {
      name: 'updateTableHeight',
      code: function() {
        // Find the distance from the top of the table to the top of the screen.
        var distanceFromTop = this.table_.el().getBoundingClientRect().y;

        // Calculate the remaining space we have to make use of.
        var remainingSpace = window.innerHeight - distanceFromTop;

        // Set the limit such that we make maximum use of the space without
        // overflowing.
        this.limit = Math.max(1, Math.floor((remainingSpace - this.TABLE_HEAD_HEIGHT) / this.rowHeight));
      }
    }
  ]
});

@@ -2072,32 +2072,210 @@
 Height;%0A      %7D%0A
+    %7D,%0A    %7B%0A      name: 'scrollbar_',%0A      documentation: %60%0A        A reference to the scrollbar element so we can update the height after%0A        the view has loaded.%0A      %60%0A
     %7D%0A  %5D,%0A%0A  me
@@ -2372,11 +2372,13 @@
 te(%7B
+ 
 fn:
+ 
 this
@@ -2389,16 +2389,17 @@
 AOUpdate
+ 
 %7D)));%0A  
@@ -4220,16 +4220,17 @@
       %7D)
+;
 %0A      %7D

Fix some linter errors