(function() {
    'use strict';

    var ResultTables = (function() {
      // Init handsontable which can be edited
      function _initEditableHandsOnTable(root) {
        root.find('.editable-table').each(function() {
          var $container = $(this).find('.hot');
          var data = null;
          var contents = $(this).find('.hot-contents');
          var metadata = $(this).find('.hot-metadata').val() || {};
          if (contents.attr('value')) {
            data = JSON.parse(contents.attr('value')).data;
          }

          $container.handsontable({
            data: data,
            startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
            startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
            minRows: 1,
            minCols: 1,
            rowHeaders: true,
            colHeaders: true,
            contextMenu: true,
            cell: metadata.cells || [],
            formulas: true,
            preventOverflow: 'horizontal',
            afterChange: function() {
              $container.addClass(GLOBAL_CONSTANTS.HAS_UNSAVED_DATA_CLASS_NAME);
            }
          });
        });
      }

      function _onSubmitExtractTable($form) {
        $form.submit(function(){
          var hot = $('.hot').handsontable('getInstance');
          var contents = $('.hot-contents');
          var metadata = $('.hot-metadata');
          var data = JSON.stringify({data: hot.getData()});
          contents.attr('value', data);
          metadata.attr('value', JSON.stringify({cells: hot.getCellsMeta().map(
            (x) => {
              const {row, col} = x;
              const plugins = hot.plugin;
              const cellId = plugins.utils.translateCellCoords({row, col});
              const calculated = plugins.matrix.getItem(cellId)?.value ||
                hot.getDataAtCell(row, col) ||
                null;

              if (x) {
                return {
                  col: x.col,
                  row: x.row,
                  className: x.className || '',
                  calculated: calculated
                }
              } else {
                return null
              }
            }).filter(e => { return e !== null})
          }))
          return true;
        });
      }

      // Save result table callback
      function newResultTableCallback() {
        $('.new-result-tables-buttons .save-result').on('click', (event) => {
          Results.processResult(event, Results.ResultTypeEnum.TABLE);
        });
      }

      // Save result table callback
      function saveResultTableCallback() {
        $('.edit-result-tables-buttons .save-result').on('click', (event) => {
          Results.processResult(event, Results.ResultTypeEnum.TABLE);
        });
      }

      // Apply ajax callback to form
      function _formAjaxResultTable($form, $prevResult) {
        $form.on('ajax:success', function(e, data) {
          var $result;
          if ($prevResult) $prevResult.remove();
          $form.after(data.html);
          $result = $(this).next();
          initFormSubmitLinks($result);
          $(this).remove();

          applyEditResultTableCallback();
          Results.initHandsOnTables($result);
          Results.toggleResultEditButtons(true);
          Results.expandResult($result);
          Comments.init();
          initNewResultTable();
        });
        $form.on('ajax:error', function(e, xhr, status, error) {
          var data = xhr.responseJSON;
          $form.renderFormErrors('result', data);
        });
      }

      // Edit result table button behaviour
      function applyEditResultTableCallback() {
        $('.edit-result-table').off('ajax:success ajax:error').on('ajax:success', function(e, data) {
          var $result = $(this).closest('.result');
          var $form = $(data.html);
          var $prevResult = $result;
          $result.after($form);
          $prevResult.hide();

          _formAjaxResultTable($form, $prevResult);
          _initEditableHandsOnTable($form);
          _onSubmitExtractTable($form);

          // Cancel button
          $form.find('.cancel-edit').click(function () {
            $prevResult.show();
            $form.remove();
            applyEditResultTableCallback();
            Results.toggleResultEditButtons(true);
          });

          Results.toggleResultEditButtons(false);

          $('#result_name').focus();
          saveResultTableCallback();
        });
      }

      // New result text behaviour
      function initNewResultTable() {
        $('#new-result-table').on('click', function(event) {
          event.preventDefault();
          event.stopImmediatePropagation();
          event.stopPropagation();
          var $btn = $(this);
          $btn.off();
          animateSpinner(null, true);
          // get new result form
          $.ajax({
            url: $btn.data('href'),
            method: 'GET',
            success: function(data) {
              var $form = $(data.html);
              animateSpinner(null, false);
              $('#results').prepend($form);
              _formAjaxResultTable($form);
              _initEditableHandsOnTable($form);
              _onSubmitExtractTable($form);
              Results.initCancelFormButton($form, initNewResultTable);
              Results.toggleResultEditButtons(false);
              $('#result_name').focus();
              newResultTableCallback();
            },
            error: function() {
              animateSpinner(null, false);
              initNewResultTable();
            }
          });
        });
      }

      var publicAPI = Object.freeze({
        initNewResultTable: initNewResultTable,
        applyEditResultTableCallback: applyEditResultTableCallback
      });

      return publicAPI;
    })();

    ResultTables.initNewResultTable();
    ResultTables.applyEditResultTableCallback();
})();
