window.affix = {
  register: [],
  enabled: {
    tableScrollbars: false,
    sidebar: false,
    formActions: false
  },
  prepareHeads: function ($theads) {
    $theads.each(function () {
      var css = [];
      var $this = $(this);
      var $rows = $this.find('tr');
      $rows.each(function () {
        var maxHeight = 0;
        var $this = $(this);
        var $parent = $this.parent();
        var $cells = $this.find('th,td');

        $cells.each(function (index) {
          var $this = $(this);
          css[index] = {
            paddingTop: $this.css("paddingTop"),
            paddingRight: $this.css("paddingRight"),
            paddingBottom: $this.css("paddingBottom"),
            paddingLeft: $this.css("paddingLeft")
          };
          var currentHeight = $this.height();
          if (currentHeight > maxHeight) {
            maxHeight = currentHeight;
          }
        });

        $this.detach();
        $cells.each(function (index) {
          var $this = $(this);
          $this.append('<div class="affix-cell-wrap" style="padding:' + css[index].paddingTop + ' ' + css[index].paddingRight + ' ' + css[index].paddingBottom + ' ' + css[index].paddingLeft + '; z-index: 1; height: ' + (2 + maxHeight) + 'px ;">' + $this.html() + '</div>');
          $this.find('.affix-cell-wrap .editable-parent span.icon-edit').remove();
        });
        $parent.append($this);
      });
    });
    return $theads;
  },
  recalculateHeads: function ($theads) {
    $theads.each(function () {
      var maxHeight = 0;
      var $this = $(this);
      var $cells = $this.find('th,td');
      $cells.each(function () {
        var $this = $(this);
        var currentHeight = $this.height();
        if (currentHeight > maxHeight) {
          maxHeight = currentHeight;
        }
      });
      $cells.each(function (index) {
        var $this = $(this);
        // increase height of fake thead cells to cover real ones
        $this.find('.affix-cell-wrap').css({'height': 2 + maxHeight});
      });
    });
  },
  preInit: function () {
    affix.register['main'] = false;
    affix.register['document'] = false;
    affix.register['topMenu'] = false;
    affix.register['sidebar'] = false;
    affix.register['tableScrolls'] = false;
    affix.register['tableHeads'] = false;
    affix.register['formActions'] = false;
    affix.prepareHeads(ERUI.tableHeads);
    $(document).on("erui_interface_change_horizontal", function () {
      affix.recalculateHeads(ERUI.tableHeads);
    });
    affix.init(true);
  },
  reInit: function () {
    affix.init(false);
  },
  init: function (reset) {
    affix.register['window'] = {height: window.innerHeight};
    if (!$.fx.off && !ERUI.isMobile) {
      if (ERUI.main && ERUI.main.length > 0) {
        var main = {
          element: ERUI.main,
          position: ERUI.main[0].getBoundingClientRect(),
          scroll: 0
        };
        affix.register['main'] = main;
      }

      if (ERUI.html && ERUI.html.length > 0) {
        var document = {
          element: ERUI.html,
          position: ERUI.html[0].getBoundingClientRect(),
          scroll: 0
        };
        affix.register['document'] = document;
      }

      if (ERUI.topMenu && ERUI.topMenu.length > 0) {
        var topMenu = {};
        topMenu.element = ERUI.topMenu;
        topMenu.position = topMenu.element[0].getBoundingClientRect();
        affix.register['topMenu'] = topMenu;
      }

      if (ERUI.sidebar && ERUI.sidebar.length > 0) {
        var sidebar = {};
        sidebar.element = ERUI.sidebar;
        sidebar.position = sidebar.element[0].getBoundingClientRect();
        sidebar.fix = {};
        sidebar.attached = false;
        sidebar.fix.element = sidebar.element.find('#sidebar_inner,#easy_grid_sidebar_inner').not('.edit');
        if (sidebar.fix.element && sidebar.fix.element.length > 0) {
          sidebar.fix.position = sidebar.fix.element[0].getBoundingClientRect();
          sidebar.fix.parent = {};
          sidebar.fix.parent.element = sidebar.fix.element.parent();
          if (sidebar.fix.parent.element && sidebar.fix.parent.element.length > 0) {
            sidebar.fix.parent.position = sidebar.fix.parent.element[0].getBoundingClientRect();
            sidebar.fix.width = sidebar.fix.element[0].clientWidth;
            sidebar.fix.next = sidebar.fix.element.next();
            if (reset) {
              sidebar.fix.element.css({
                zIndex: 1,
                position: 'relative',
                willChange: 'transform',
                width: sidebar.fix.width,
                MsTransform: 'translate(0,0)',
                WebkitTransform: 'translate(0,0)',
                transform: 'translate(0,0)'
              });
            }
            affix.enabled.sidebar = true;
            sidebar.offset = 20;
            affix.register['sidebar'] = sidebar;
          }
        }

        var sideScrollEl = ERUI.sidebar.find('#sidebar_content, #easy_grid_sidebar_content').not('.edit');
        if (sideScrollEl && sideScrollEl.length > 0) {
          var footerEl = sideScrollEl.next('#sidebar_footer');
          var footerHeight = footerEl.outerHeight();
          var windowHeight = ERUI.window.outerHeight();
          ERUI.headerHeight = ERUI.header.outerHeight();
          var headerHeight = ERUI.headerHeight;
          ERUI.pageTabsHeight = ERUI.pageTabs.outerHeight();
          var pageTabsHeight = ERUI.pageTabsHeight;
          var topMenuHeight = ERUI.topMenu.outerHeight();
          var sideScrollElOffs = sideScrollEl[0].offsetTop;
          var sidebarOffsTop = ERUI.sidebar.children().first()[0].offsetTop;
          ERUI.sidebarOffsTop = sidebarOffsTop;
          var sideScrollElHight = windowHeight - headerHeight - topMenuHeight - sideScrollElOffs - pageTabsHeight - 1;
          ERUI.sideScrollElHight = headerHeight ? sideScrollElHight : (sideScrollElHight - sidebarOffsTop);

          sideScrollEl = sideScrollEl.children('.easy-scroller');
          ERUI.sideScrollEl = sideScrollEl;
          sideScrollEl.children().first().css({paddingBottom: footerHeight});
          sideScrollEl.css({
            height: ERUI.sideScrollElHight,
            overflow: 'hidden',
            position: 'relative'
          }).perfectScrollbar({
            suppressScrollX: true,
            includePadding: true,
            wheelPropagation: true,
            swipePropagation: true
          }).scroll(function () {
            if (sideScrollEl.scrollTop() > 0) {
              sideScrollEl.parent().addClass('scrolled');
            } else {
              sideScrollEl.parent().removeClass('scrolled');
            }
          });

          footerEl.css({
            position: 'absolute',
            left: 0,
            right: 0,
            bottom: 0
          });
        }

      }

      if (ERUI.tableScrolls && ERUI.tableScrolls.length > 0) {
        var tableScrolls = {};
        tableScrolls.wrappers = {};
        tableScrolls.xbars = {};
        tableScrolls.wrappers.element = ERUI.tableScrolls;
        tableScrolls.wrappers.position = [];
        tableScrolls.xbars.element = [];
        tableScrolls.xbars.position = [];
        tableScrolls.xbars.element = tableScrolls.wrappers.element.children(".ps-scrollbar-x-rail");
        tableScrolls.wrappers.element.each(function (index) {
          tableScrolls.wrappers.position[index] = tableScrolls.wrappers.element[index].getBoundingClientRect();
          tableScrolls.xbars.position[index] = tableScrolls.xbars.element[index].getBoundingClientRect();
        });
        if (reset) {
          tableScrolls.xbars.element.css({
            willChange: 'transform',
            MsTransform: 'translate(0,0)',
            WebkitTransform: 'translate(0,0)',
            transform: 'translate(0,0)'
          });
          affix.register['tableScrolls'] = tableScrolls;
        }
      }

      if (ERUI.tableHeads && ERUI.tableHeads.length > 0) {
        var tableHeads = {};
        tableHeads.element = ERUI.tableHeads;
        tableHeads.parent = {};
        tableHeads.fake = {};
        tableHeads.position = [];
        tableHeads.parent.element = [];
        tableHeads.parent.position = [];
        tableHeads.fake.elements = [];
        tableHeads.element.each(function (index) {
          if (tableHeads.element[index].parentNode === null) {
            return;
          }
          tableHeads.parent.element[index] = tableHeads.element[index].parentNode;
          tableHeads.position[index] = tableHeads.element[index].getBoundingClientRect();
          tableHeads.parent.position[index] = tableHeads.parent.element[index].getBoundingClientRect();
          tableHeads.fake.elements[index] = $(this).find('.affix-cell-wrap');
          if (reset) {
            tableHeads.fake.elements[index].each(function () {
              this.style.willChange = 'transform';
              this.style.MsTransform = 'translate(0,0)';
              this.style.WebkitTransform = 'translate(0,0)';
              this.style.transform = 'translate(0,0)';
            });
          }
        });
        affix.register['tableHeads'] = tableHeads;
      }

      if (ERUI.formActions && ERUI.formActions.length > 0) {
        var formActions = {};
        formActions.element = ERUI.formActions;
        formActions.forms = {};
        formActions.position = [];
        formActions.height = [];
        formActions.forms.height = [];
        formActions.forms.position = [];
        formActions.forms.element = formActions.element.closest('form');
        formActions.element.each(function (index) {
          formActions.forms.position[index] = formActions.forms.element[index].getBoundingClientRect();
          formActions.position[index] = this.getBoundingClientRect();
          formActions.height[index] = this.offsetHeight;
          formActions.forms.height[index] = formActions.forms.element[index].offsetHeight;
          $(formActions.forms.element[index]).css({
            position: "relative",
            paddingBottom: 20 + formActions.height[index] + 'px'
          });
        });
        if (reset) {
          formActions.element.css({
            willChange: 'transform,left,right',
            positon: 'absolute',
            left: '0',
            right: '0'
          });
        }
        affix.register['formActions'] = formActions;
      }
    }
  },
  read: function () {
    var sidebar = affix.register['sidebar'];
    if (sidebar && sidebar.fix.element) {
      sidebar.position = sidebar.element[0].getBoundingClientRect();
      sidebar.fix.position = sidebar.fix.element[0].getBoundingClientRect();
      sidebar.fix.parent.position = sidebar.fix.parent.element[0].getBoundingClientRect();
    } else {
      affix.enabled.sidebar = false;
    }

    var tableScrolls = affix.register['tableScrolls'];
    if (tableScrolls && tableScrolls.wrappers.element) {
      tableScrolls.wrappers.element.each(function (index) {
        tableScrolls.wrappers.position[index] = tableScrolls.wrappers.element[index].getBoundingClientRect();
      });
    }
    var tableHeads = affix.register['tableHeads'];
    if (tableHeads && tableHeads.element) {
      tableHeads.element.each(function (index) {
        if (tableHeads.parent.element[index] === undefined)
          return;
        tableHeads.position[index] = tableHeads.element[index].getBoundingClientRect();
        tableHeads.parent.position[index] = tableHeads.parent.element[index].getBoundingClientRect();
      });
    }
    var formActions = affix.register['formActions'];
    if (formActions) {
      formActions.element.each(function (index) {
        formActions.forms.position[index] = formActions.forms.element[index].getBoundingClientRect();
        formActions.position[index] = formActions.element[index].getBoundingClientRect();
      });
    }
  },
  tableScrolls: function () {
    var tableScrolls = affix.register['tableScrolls'];
    if (tableScrolls) {
      var scroller = affix.register['window'];
      tableScrolls.xbars.element.each(function (index) {
        var wrapperPosition = tableScrolls.wrappers.position[index];
        var formBottomDistance = -1 * (scroller.height + 1 - wrapperPosition.top - wrapperPosition.height);
        if (formBottomDistance > 0) {
          this.style.MsTransform = 'translate(0,' + (-formBottomDistance) + 'px)';
          this.style.WebkitTransform = 'translate(0,' + (-formBottomDistance) + 'px)';
          this.style.transform = 'translate(0,' + (-formBottomDistance) + 'px)';
        } else {
          this.style.MsTransform = 'translate(0,0)';
          this.style.WebkitTransform = 'translate(0,0)';
          this.style.transform = 'translate(0,0)';
        }
      });
    }
  },
  tableHeads: function () {
    var tableHeads = affix.register['tableHeads'];
    if (tableHeads) {
      var menuPosition = affix.register['topMenu'].position;
      var mh;
      if (menuPosition) {
        mh = menuPosition.height;
      } else {
        mh = affix.register['main'].offsetTop;
      }
      tableHeads.element.each(function (index) {
        var wrapperPosition = tableHeads.parent.position[index];
        var formTopDistance = mh - wrapperPosition.top - 1;
        if (wrapperPosition.top < menuPosition.height && wrapperPosition.top + wrapperPosition.height - 2 * tableHeads.position[index].height > menuPosition.height) {
          tableHeads.fake.elements[index].each(function () {
            this.style.MsTransform = 'translate(0,' + (formTopDistance) + 'px)';
            this.style.WebkitTransform = 'translate(0,' + (formTopDistance) + 'px)';
            this.style.transform = 'translate(0,' + (formTopDistance) + 'px)';
            //this.style.opacity = '1';
          });
        } else {
          tableHeads.fake.elements[index].each(function () {
            this.style.MsTransform = 'translate(0,0)';
            this.style.WebkitTransform = 'translate(0,0)';
            this.style.transform = 'translate(0,0)';
            //this.style.opacity = '0';
          });
        }
      });
    }
  },
  formActions: function () {
    var formActions = affix.register['formActions'];
    if (formActions) {
      var topMenu = affix.register['topMenu'];
      var scroller = affix.register['window'];
      formActions.element.each(function (index) {
        var formPosition = formActions.forms.position[index];
        var position = formActions.position[index];
        var formBottomDistance = -1 * (scroller.height - formPosition.top - formActions.forms.height[index]);
        if (formBottomDistance > 0) {
          if (formPosition.top < scroller.height - position.height + 20) {
            this.style.position = 'fixed';
            this.style.left = 20 + formPosition.left + 'px';
            this.style.width = formPosition.width - 42 + 'px';
            this.style.top = 'auto';
            this.style.bottom = '0px';
            this.style.marginBottom = '0';
          } else {
            this.style.position = 'absolute';
            this.style.top = '-21px';
            this.style.left = '0';
            this.style.right = '0';
            this.style.width = 'auto';
            this.style.bottom = 'auto';
          }
        } else {
          this.style.position = 'absolute';
          this.style.left = '0';
          this.style.right = '0';
          this.style.top = 'auto';
          this.style.width = 'auto';
          this.style.bottom = 'inherit';
        }
      });
    }
  },
  sidebar: function () {
    if (affix.enabled.sidebar) {
      var topMenu = affix.register['topMenu'];
      var sidebar = affix.register['sidebar'];
      var position = sidebar.position.top - topMenu.position.height; //+ sidebar.offset;
      if (position < 0) {
        if (!sidebar.attached) {
          ERUI.document.trigger("erui_affix_sidebar_attached");
          sidebar.attached = true;
          sidebar.fix.element.css({
            position: 'fixed',
            top: topMenu.position.height + sidebar.offset + 'px'
          });
        }
      } else {
        if (sidebar.attached) {
          ERUI.document.trigger("erui_affix_sidebar_detached");
          sidebar.attached = false;
          sidebar.fix.element.css({
            position: 'relative',
            top: 'auto'
          });
        }
      }
    }
  }
};
