'use strict';

var RCV = require('@progress/telerik-common-report-viewer');

function HistoryManager(options) {
  var controller = options.controller;
  if (!controller) {
    throw "No controller (telerikReporting.reportViewerController) has been specified.";
  }
  var settings = options.settings;
  var history = settings.getHistory() || { records: [], position: -1 };
  controller.on("loadedReportChange", () => {
    addToHistory(true);
  }).on("currentPageChanged", () => {
    updatePageInfo();
  }).onAsync("reportLoadComplete", async () => {
    addToHistory(false);
  }).on("clientExpired", () => {
    var records = history.records;
    for (var i = 0; i < records.length; i++) {
      records[i].reportDocumentId = null;
    }
  });
  function getCurrentRecord() {
    var records = history.records;
    if (records.length > 0) {
      return records[history.position];
    }
    return null;
  }
  function pushRecord(rec) {
    var records = history.records;
    var position = history.position;
    records = Array.prototype.slice.call(records, 0, position + 1);
    records.push(rec);
    history.records = records;
    history.position = records.length - 1;
    saveSettings();
  }
  function saveSettings() {
    settings.setHistory(history);
  }
  function updatePageInfo() {
    var currentRecord = getCurrentRecord();
    if (currentRecord) {
      currentRecord.pageNumber = controller.getCurrentPageNumber();
      currentRecord.viewMode = controller.getViewMode();
      currentRecord.reportDocumentId = controller.getReportDocumentId();
      saveSettings();
    }
  }
  function addToHistory(temp) {
    removeTempRecordsFromHistory();
    var currentRecord = getCurrentRecord();
    var rs = controller.getReportSource();
    var reportSources = { firstReportSource: currentRecord?.reportSource, secondReportSource: rs };
    if (!currentRecord || !RCV.reportSourcesAreEqual(reportSources)) {
      pushRecord({
        reportSource: rs,
        pageNumber: 1,
        temp
      });
    }
  }
  function exec(currentRecord, reportChanged) {
    controller.setReportDocumentId(currentRecord.reportDocumentId);
    controller.setViewMode(currentRecord.viewMode);
    controller.setReportSource(currentRecord.reportSource);
    controller.refreshReport(false, currentRecord.reportDocumentId, reportChanged);
    controller.navigateToPage(currentRecord.pageNumber);
  }
  function canMove(step) {
    var position = history.position;
    var length = history.records.length;
    var newPos = position + step;
    return 0 <= newPos && newPos < length;
  }
  function move(step) {
    var position = history.position;
    var length = history.records.length;
    var newPos = position + step;
    if (newPos < 0) {
      newPos = 0;
    } else if (newPos >= length) {
      newPos = length - 1;
    }
    if (newPos != position) {
      var currentRecord = getCurrentRecord();
      var currentReport = currentRecord.reportSource ? currentRecord.reportSource.report : "";
      history.position = newPos;
      saveSettings();
      var newRecord = getCurrentRecord();
      var newReport = newRecord.reportSource ? newRecord.reportSource.report : "";
      exec(newRecord, currentReport !== newReport);
    }
  }
  function removeTempRecordsFromHistory() {
    var lastIndex = history.records.length - 1;
    while (lastIndex >= 0) {
      if (history.records[lastIndex].temp === true) {
        history.records.splice(lastIndex, 1);
        if (history.position >= lastIndex) {
          history.position--;
        }
      } else {
        break;
      }
      lastIndex--;
    }
  }
  return {
    back: () => {
      move(-1);
    },
    forward: () => {
      move(1);
    },
    canMoveBack: () => {
      return canMove(-1);
    },
    canMoveForward: () => {
      return canMove(1);
    },
    loadCurrent: () => {
      var rec = getCurrentRecord();
      if (rec) {
        exec(rec, false);
      }
      return Boolean(rec);
    }
  };
}

exports.HistoryManager = HistoryManager;
