var model = null;

// Protocol helper functions
function getHttpProtocol() {
  return window.location.protocol === 'https:' ? 'https://' : 'http://';
}

function getWsProtocol() {
  return window.location.protocol === 'https:' ? 'wss://' : 'ws://';
}

// use these two when running MR server
var baseurl = "/sources/";
var wsurl = getWsProtocol()+window.location.hostname+":"+window.location.port+"/remote";
// use these two when running standalone
//var baseurl = getHttpProtocol()+"127.0.0.1:8080/sources/";
//var wsurl = getWsProtocol()+"127.0.0.1:8080/remote";

var originalRows, originalColumns;

function MRRemoteModel() {
  var self = this;

  self.sources = ko.observableArray();
  self.destinations = ko.observableArray();
  self.viewers = ko.observableArray();
  self.numberOfViewersSelected = ko.observable(0);

  self.canGangStop = ko.computed(function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        self.viewers()[i].selectedSource().isRecording()
      ) {
        return true;
      }
    }
    return false;
  }, self);
  self.canGangPause = ko.computed(function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        self.viewers()[i].selectedSource().isRecording() &&
        self.viewers()[i].selectedSource().isPaused() === false
      ) {
        return true;
      }
    }
    return false;
  }, self);
  self.canGangRecord = ko.computed(function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        (self.viewers()[i].selectedSource().isRecording() === false ||
          self.viewers()[i].selectedSource().isPaused() === true)
      ) {
        return true;
      }
    }
    return false;
  }, self);

  self.gangRecord = function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        (self.viewers()[i].selectedSource().isRecording() === false ||
          self.viewers()[i].selectedSource().isPaused())
      ) {
        var action = self.viewers()[i].selectedSource().isPaused()
          ? "resume"
          : "record";
        $.ajax(
          baseurl +
            encodeURIComponent(self.viewers()[i].selectedSource().uniqueID) +
            "/" +
            action
        );
      }
    }
  };

  self.gangStop = function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        self.viewers()[i].selectedSource().isRecording()
      ) {
        $.ajax(
          baseurl +
            encodeURIComponent(self.viewers()[i].selectedSource().uniqueID) +
            "/stop"
        );
      }
    }
  };

  self.gangPause = function () {
    for (var i = 0; i < self.viewers().length; i++) {
      if (
        self.viewers()[i].isSelected() &&
        self.viewers()[i].selectedSource() &&
        self.viewers()[i].selectedSource().isRecording() &&
        self.viewers()[i].selectedSource().isPaused() === false
      ) {
        $.ajax(
          baseurl +
            encodeURIComponent(self.viewers()[i].selectedSource().uniqueID) +
            "/pause"
        );
      }
    }
  };

  self.showTimerPopover = function () {
    var button = $(".timerButton:visible");
    if (button.length) {
      var offset = button.offset();
      var timerPopOver = $("#timerPopOver");

      timerPopOver.css({
        display: "block",
        visibility: "hidden",
      });

      var popoverWidth = timerPopOver.outerWidth();
      var popoverHeight = timerPopOver.outerHeight();

      timerPopOver.css({
        left:
          Math.max(
            5,
            offset.left + button.outerWidth() / 2 - popoverWidth / 2
          ) + "px",
        top: offset.top - popoverHeight - 15 + "px",
        visibility: "visible",
      });
    }
  };
}

function Viewer() {
  var self = this;
  self.selectedSource = ko.observable(null);
  self.isSelected = ko.observable(false);
  self.previewImage = null;
  self.shouldDraw = false;
  self.shouldFetch = false;
  self.animationRequestID = null;
  self.context = null;

  self.toggleDestinationsPopOver = function (data, event) {
    var label = $(event.target).closest(".destinationsLabel");
    var popover = label.siblings(".destinationsPopOver");

    if (!popover.hasClass("visible")) {
      var labelRect = label[0].getBoundingClientRect();
      var arrowOffset = 18;
      popover.css({
        top: labelRect.bottom + 10 + "px",
        left: labelRect.right - popover.width() + "px",
      });

      popover.find("::after").css({
        right: arrowOffset + "px",
        top: "-6px",
      });

      popover.css("visibility", "visible");
      setTimeout(function () {
        popover.addClass("visible");
      }, 10);
    } else {
      popover.removeClass("visible");
      setTimeout(function () {
        popover.css("visibility", "hidden");
      }, 200);
    }
  };

  self.closeDestinationsPopOver = function (data, event) {
    var popover = $(event.target).closest(".destinationsPopOver");
    popover.removeClass("visible");
    setTimeout(function () {
      popover.css("visibility", "hidden");
    }, 200);
  };

  self.isDestinationSelected = function (destinationId) {
    if (!self.selectedSource()) return false;
    return ko.computed({
      read: function () {
        if (!self.selectedSource()) return false;
        return (
          self
            .selectedSource()
            .selectedDestinations()
            .indexOf(destinationId) !== -1
        );
      },
      write: function (value) {
        if (!self.selectedSource()) return;
        var destinations = self.selectedSource().selectedDestinations.slice();
        var index = destinations.indexOf(destinationId);

        if (value && index === -1) {
          destinations.push(destinationId);
        } else if (!value && index !== -1) {
          destinations.splice(index, 1);
        }

        self.selectedSource().selectedDestinations(destinations);

        self.applyDestinationChanges();
      },
    });
  };

  self.selectAllDestinations = function () {
    if (!self.selectedSource()) return;

    var allDestinations = [];
    ko.utils.arrayForEach(model.destinations(), function (destination) {
      allDestinations.push(destination.uniqueID);
    });

    self.selectedSource().selectedDestinations(allDestinations);

    self.applyDestinationChanges();
  };

  self.clearAllDestinations = function () {
    if (!self.selectedSource()) return;
    self.selectedSource().selectedDestinations([]);

    self.applyDestinationChanges();
  };

  self.applyDestinationChanges = function () {
    if (!self.selectedSource()) return;

    $.ajax({
      url:
        baseurl +
        encodeURIComponent(self.selectedSource().uniqueID) +
        "/destinations",
      type: "PUT",
      data: JSON.stringify(self.selectedSource().selectedDestinations()),
      contentType: "application/json",
    });
  };

  self.isRecording = ko.computed(function () {
    return self.selectedSource() && self.selectedSource().isRecording();
  });
  self.selectViewer = function () {
    if (self.selectedSource()) {
      self.isSelected(!self.isSelected());
      if (self.isSelected()) {
        model.numberOfViewersSelected(model.numberOfViewersSelected() + 1);
      } else {
        model.numberOfViewersSelected(model.numberOfViewersSelected() - 1);
      }
    }
  };
  self.drawPreview = function () {
    if (self.shouldDraw && self.context && self.previewImage) {
      try {
        self.context.clearRect(
          0,
          0,
          self.context.canvas.width,
          self.context.canvas.height
        );

        if (self.previewImage && self.previewImage.width) {
          self.context.drawImage(
            self.previewImage,
            0,
            0,
            self.previewImage.width,
            self.previewImage.height,
            0,
            0,
            self.context.canvas.width,
            self.context.canvas.height
          );
        }

        self.shouldDraw = false;
        self.shouldFetch = true;
      } catch (e) {
        console.warn("Error drawing preview: ", e);
        self.shouldDraw = false;
      }
    }

    if (self.context) {
      self.animationRequestID = window.requestAnimationFrame(self.drawPreview);
    }
  };

  self.startPreview = function () {
    try {
      var canvas = $("canvas")[model.viewers.indexOf(self)];
      if (canvas) {
        var container = $(canvas).parent()[0];
        var rect = container.getBoundingClientRect();
        canvas.width = rect.width;
        canvas.height = rect.height;

        self.context = canvas.getContext("2d");
        self.animationRequestID = requestAnimationFrame(self.drawPreview);
        self.shouldFetch = true;
      } else {
        console.warn("Canvas not found for viewer");
      }
    } catch (e) {
      console.error("Error starting preview: ", e);
    }
  };

  self.stopPreview = function () {
    try {
      if (self.animationRequestID) {
        cancelAnimationFrame(self.animationRequestID);
        self.animationRequestID = null;
      }
      self.previewImage = null;
      self.shouldFetch = false;

      if (self.context) {
        self.context.clearRect(
          0,
          0,
          self.context.canvas.width,
          self.context.canvas.height
        );
      }
    } catch (e) {
      console.warn("Error stopping preview: ", e);
    }
  };
  self.selectedSource.subscribe(
    function (oldValue) {
      if (oldValue) {
        self.stopPreview();
      }
    },
    null,
    "beforeChange"
  );
  self.selectedSource.subscribe(function (newValue) {
    if (newValue) {
      self.consecutiveFailures = 0;
      self.lastWarningFetchAttempt = 0;

      for (var i = 0; i < model.viewers().length; i++) {
        if (
          model.viewers()[i] != self &&
          model.viewers()[i].selectedSource() == newValue
        ) {
          model.viewers()[i].selectedSource(null);
        }
      }
      self.startPreview();

      saveViewerSelections();
    }
  });
}

function saveViewerSelections() {
  var selections = [];
  for (var i = 0; i < model.viewers().length; i++) {
    var viewer = model.viewers()[i];
    if (viewer.selectedSource()) {
      selections[i] = viewer.selectedSource().uniqueID;
    }
  }
  localStorage.setItem("viewerSelections", JSON.stringify(selections));
}

function loadViewerSelections() {
  try {
    var savedSelections = localStorage.getItem("viewerSelections");
    if (savedSelections) {
      savedSelections = JSON.parse(savedSelections);

      if (savedSelections && savedSelections.length > 0) {
        for (
          var i = 0;
          i < Math.min(savedSelections.length, model.viewers().length);
          i++
        ) {
          if (savedSelections[i]) {
            var sourceFound = false;
            for (var j = 0; j < model.sources().length; j++) {
              if (model.sources()[j].uniqueID === savedSelections[i]) {
                model.viewers()[i].selectedSource(model.sources()[j]);
                sourceFound = true;
                break;
              }
            }

            if (!sourceFound) {
              model.viewers()[i].selectedSource(null);
            }
          }
        }
      }
    }
  } catch (e) {
    console.error("Error loading saved viewer selections:", e);
  }
}

function Source(inData) {
  var self = this;
  self.uniqueID = inData.unique_id;
  self.displayName = ko.observable(inData.display_name);
  self.deviceName = inData.device_name;
  self.videoFormat = ko.observable(inData.video_format);
  self.isRecording = ko.observable(inData.is_recording);
  self.isPaused = ko.observable(inData.is_paused);
  self.lastWarning = ko.observable(null);
  self.selectedDestinations = ko.observableArray(inData.selected_destinations);

  self.description = ko.computed(function () {
    return self.deviceName + " (" + self.videoFormat() + ")";
  });

  self.selectedDestinationsLabel = ko.computed(function () {
    const count = self.selectedDestinations().length;

    if (count > 0) {
      for (var i = 0; i < model.destinations().length; i++) {
        var destination = model.destinations()[i];
        for (var j = 0; j < self.selectedDestinations().length; j++) {
          if (destination.uniqueID === self.selectedDestinations()[j]) {
            if (count === 1) {
              return destination.name;
            }
            return destination.name;
          }
        }
      }
    }
    return "Destinations";
  });

  self.destinationsCount = ko.computed(function () {
    return self.selectedDestinations().length;
  });

  self.hasWarning = ko.computed(function () {
    return self.lastWarning() != null ? true : false;
  });
}

function Destination(inData) {
  var self = this;
  self.uniqueID = inData.unique_id;
  self.name = inData.name;
  self.path = inData.path;
}

model = new MRRemoteModel();

function fetchPreview() {
  for (var i = 0; i < model.viewers().length; i++) {
    var viewer = model.viewers()[i];
    if (viewer.shouldFetch && viewer.selectedSource()) {
      var source = viewer.selectedSource();
      var hasWarning = source && source.lastWarning();
      if (hasWarning && viewer.consecutiveFailures > 0) {
        viewer.lastWarningFetchAttempt =
          viewer.lastWarningFetchAttempt || Date.now();
        var now = Date.now();
        var timeSinceLastAttempt = now - viewer.lastWarningFetchAttempt;
        if (timeSinceLastAttempt < 3000) {
          continue;
        }
        viewer.lastWarningFetchAttempt = now;
      }

      viewer.shouldFetch = false;
      viewer.previewImage = new Image();

      viewer.previewImage.onload = (function (loadedViewer) {
        return function () {
          if (loadedViewer.selectedSource()) {
            if (loadedViewer.previewImage && loadedViewer.previewImage.width) {
              loadedViewer.shouldDraw = true;
              loadedViewer.consecutiveFailures = 0;
            } else {
              loadedViewer.shouldFetch = true;
            }
          }
        };
      })(viewer);

      viewer.previewImage.onerror = (function (loadedViewer) {
        return function () {
          console.warn("Error loading preview image");
          loadedViewer.consecutiveFailures =
            (loadedViewer.consecutiveFailures || 0) + 1;

          var backoffDelay = Math.min(
            30000,
            Math.pow(2, loadedViewer.consecutiveFailures - 1) * 1000
          );

          setTimeout(function () {
            if (loadedViewer.selectedSource()) {
              loadedViewer.shouldFetch = true;
            }
          }, backoffDelay);
        };
      })(viewer);

      try {
        viewer.previewImage.src =
          baseurl +
          encodeURIComponent(viewer.selectedSource().uniqueID) +
          "/thumbnail?time=" +
          Date.now();
      } catch (e) {
        console.error("Error setting image source: ", e);
        viewer.shouldFetch = true;
      }
    }
  }

  window.setTimeout(fetchPreview, 1000 / 30);
}

function updateViewerInfo(index) {
  if (index == model.viewers().length) {
    window.setTimeout(updateViewersInfo, 1000 / 60);
  } else {
    var source = model.viewers()[index].selectedSource();
    if (source) {
      $.getJSON(
        baseurl + encodeURIComponent(source.uniqueID) + "/info",
        function (data) {
          var canvaswrap = $(".canvaswrap").eq(index);
          var vuMeters = canvaswrap.find(".vuMeterOverlay");

          canvaswrap.find(".vuMeter").show();

          for (var i = 0; i < 8; i++) {
            var height = 100;
            if (i < data.vu_meter_levels.length) {
              height = (1 - data.vu_meter_levels[i]) * 100;
            }
            vuMeters.eq(i).css("height", height + "%");
          }

          var timecode = data.timecode || "00:00:00:00";
          canvaswrap.find(".timecode").text(timecode).show();

          source.isRecording(data.is_recording);
          source.isPaused(data.is_paused);

          var hadWarningBefore = source.lastWarning() !== null;
          var hasWarningNow = data.last_warning !== null;

          source.lastWarning(data.last_warning ? data.last_warning : null);

          if (!hadWarningBefore && hasWarningNow) {
            model.viewers()[index].lastWarningFetchAttempt = 0;
          }

          if (hadWarningBefore && !hasWarningNow) {
            model.viewers()[index].consecutiveFailures = 0;
          }
        }
      ).always(function () {
        updateViewerInfo(index + 1);
      });
    } else {
      updateViewerInfo(index + 1);
    }
  }
}

function updateViewersInfo() {
  updateViewerInfo(0);
}

updateViewersInfo();

$("#destinationlist").hide();

$("#topmenu").on("click", "div", function () {
  if ($(this).hasClass("selected") === false) {
    $("#topmenu div").toggleClass("selected");
    $("#sourcelist, #destinationlist").toggle();
  }
});

$("#bottom").on("click", ".timerButton", function (e) {
  if (!$(this).hasClass("inactive")) {
    e.stopPropagation();
    model.showTimerPopover();
  }
});

$(document).on("click", function (e) {
  if (!$(e.target).closest("#timerPopOver, .timerButton").length) {
    $("#timerPopOver").hide();
  }
});

$("#timerPopOver")
  .on("click", ".cancel, #closeTimerPopOver", function (e) {
    e.preventDefault();
    $("#timerPopOver").hide();
  })
  .on("click", ".apply", function (e) {
    e.preventDefault();
    if ($("#timerDuration:checked").val()) {
      var duration = $("#duration").val().split(":");
      if (
        duration.length === 2 &&
        !isNaN(parseInt(duration[0])) &&
        !isNaN(parseInt(duration[1]))
      ) {
        for (var i = 0; i < model.viewers().length; i++) {
          if (
            model.viewers()[i].isSelected() &&
            model.viewers()[i].selectedSource()
          ) {
            $.ajax(
              baseurl +
                encodeURIComponent(
                  model.viewers()[i].selectedSource().uniqueID
                ) +
                "/record?duration=" +
                (parseInt(duration[0], 10) * 3600 +
                  parseInt(duration[1], 10) * 60)
            );
            break;
          }
        }
        $("#timerPopOver").hide();
      } else {
        alert("Please enter a valid duration in format hh:mm");
      }
    } else if ($("#timerDate:checked").val()) {
      var endDateAsString = $("#endDate").val();
      if (endDateAsString.length) {
        var endDate = new Date(endDateAsString);
        if (!isNaN(endDate.getTime())) {
          for (var i = 0; i < model.viewers().length; i++) {
            if (
              model.viewers()[i].isSelected() &&
              model.viewers()[i].selectedSource()
            ) {
              $.ajax(
                baseurl +
                  encodeURIComponent(
                    model.viewers()[i].selectedSource().uniqueID
                  ) +
                  "/record?end_date=" +
                  endDate.toJSON()
              );
              break;
            }
          }
          $("#timerPopOver").hide();
        } else {
          alert("Please enter a valid end date and time");
        }
      } else {
        alert("Please enter an end date and time");
      }
    }
  });

$("#viewers")
  .on("click", ".destinationsLabel", function () {
    $(this).next().css("visibility", "visible");
  })
  .on("click", "button", function () {
    $(this).parent().css("visibility", "hidden");
  });

$("#gangRecording").on("click", "button", function () {
  for (var i = 0; i < model.viewers().length; i++) {
    if (
      model.viewers()[i].isSelected() &&
      model.viewers()[i].selectedSource()
    ) {
      $.ajax({
        url:
          baseurl +
          encodeURIComponent(model.viewers()[i].selectedSource().uniqueID) +
          "/recording_name",
        type: "PUT",
        data: JSON.stringify({
          recording_name: $("#gangRecording input").val(),
        }),
        contentType: "application/json",
      });
    }
  }
});

for (var i = 0; i < 20; i++) {
  model.viewers.push(new Viewer());
}

ko.applyBindings(model);
fetchPreview();
var socket = new WebSocket(
  wsurl,
  "v1.1.main_update.movierecorder.softronmedia.com"
);

socket.onmessage = function (event) {
  var message = JSON.parse(event.data);
  switch (message.dataType) {
    case "source":
      switch (message.change) {
        case "insertion":
          $.each(message.data, function (index, inSource) {
            if (inSource.is_enabled) {
              var source = new Source(inSource);
              model.sources.push(source);
              $.ajax(
                baseurl + encodeURIComponent(source.uniqueID) + "/destinations"
              ).done(function (inSelectedDestinations) {
                source.selectedDestinations(inSelectedDestinations);
              });
            }
          });

          loadViewerSelections();
          break;
        case "removal":
          for (var i = 0; i < message.data.length; i++) {
            model.sources.remove(function (source) {
              return source.uniqueID === message.data[i];
            });
          }
          break;
        case "replacement":
          var source = new Source(message.data);
          for (var i = 0; i < model.sources().length; i++) {
            if (model.sources()[i].uniqueID == source.uniqueID) {
              if (typeof source.displayName() !== "undefined") {
                model.sources()[i].displayName(source.displayName());
              }
              if (typeof source.videoFormat() !== "undefined") {
                model.sources()[i].videoFormat(source.videoFormat());
              }
              if (typeof source.isRecording() !== "undefined") {
                model.sources()[i].isRecording(source.isRecording());
              }
              if (typeof source.isPaused() !== "undefined") {
                model.sources()[i].isPaused(source.isPaused());
              }
              if (
                message.data.selected_destinations &&
                getDifferencesBetweenTwoArrays(
                  source.selectedDestinations(),
                  model.sources()[i].selectedDestinations()
                ).length > 0
              ) {
                model
                  .sources()
                  [i].selectedDestinations(source.selectedDestinations());
              }
              break;
            }
          }
          break;
      }
      break;
    case "destination":
      switch (message.change) {
        case "insertion":
          $.each(message.data, function (index, inDestination) {
            model.destinations.push(new Destination(inDestination));
          });
          break;
        case "removal":
          for (var i = 0; i < message.data.length; i++) {
            model.destinations.remove(function (destination) {
              return destination.uniqueID === message.data[i];
            });
          }
          break;
        case "replacement":
          var destination = new Destination(message.data);
          for (var i = 0; i < model.destinations().length; i++) {
            if (model.destinations()[i].uniqueID == destination.uniqueID) {
              model.destinations.replace(model.destinations()[i], destination);
              break;
            }
          }
          break;
      }
      break;
  }
};

function onSelectedDestinationsChanged(source) {
  $.ajax({
    url: baseurl + encodeURIComponent(source.uniqueID) + "/destinations",
    type: "PUT",
    data: JSON.stringify(source.selectedDestinations()),
    contentType: "application/json",
  });
}

function getDifferencesBetweenTwoArrays(array1, array2) {
  var existingArray = [],
    differenceList = [];

  for (var i = 0; i < array1.length; i++) {
    existingArray[array1[i]] = true;
  }

  for (var i = 0; i < array2.length; i++) {
    if (existingArray[array2[i]]) {
      delete existingArray[array2[i]];
    } else {
      existingArray[array2[i]] = true;
    }
  }

  for (var difference in existingArray) {
    differenceList.push(difference);
  }

  return differenceList;
}

function updateGridAndViewers(rows, columns) {
  const viewerCount = rows * columns;
  const current = model.viewers().length;

  document.documentElement.style.setProperty("--columns", columns);
  document.documentElement.style.setProperty("--rows", rows);
  const container = document.getElementById("viewers-container");
  if (container) {
    const headerHeight = 25;
    const gap = 10;
    const availableWidth = container.clientWidth - gap * (columns - 1);
    const availableHeight = container.clientHeight - gap * (rows - 1);
    let maxCellWidthByWidth = availableWidth / columns;
    let maxCellWidthByHeight =
      (availableHeight - rows * headerHeight) / ((rows * 9) / 16);
    let cellWidth = Math.max(
      200,
      Math.min(maxCellWidthByWidth, maxCellWidthByHeight)
    );
    document.documentElement.style.setProperty(
      "--viewer-cell-width",
      cellWidth + "px"
    );
  }

  if (current > viewerCount) {
    model.viewers.splice(viewerCount, current - viewerCount);
  } else {
    for (let i = current; i < viewerCount; i++) {
      model.viewers.push(new Viewer());
    }
  }
}

$("#viewerSettingsButton").on("click", function (e) {
  e.stopPropagation();
  var popover = $("#viewerSettingsPopOver");
  originalRows = $("#rows").val();
  originalColumns = $("#columns").val();

  popover.css({
    visibility: "visible",
    display: "block",
  });

  setTimeout(function () {
    popover.addClass("visible");
  }, 10);
});

$("#closeViewerSettings, #cancelGridSettings").on("click", function () {
  var popover = $("#viewerSettingsPopOver");
  $("#rows").val(originalRows);
  $("#columns").val(originalColumns);

  popover.removeClass("visible");
  setTimeout(function () {
    popover.css("visibility", "hidden");
  }, 200);
});
$(document).on("mousedown", function (e) {
  var pop = $("#viewerSettingsPopOver");
  if (
    pop.is(":visible") &&
    !$(e.target).closest("#viewerSettingsPopOver, #viewerSettingsButton").length
  ) {
    pop.removeClass("visible");
    setTimeout(function () {
      pop.css("display", "none");
    }, 200);
  }
});

$("#applyGridSettings").on("click", function () {
  let rows = parseInt($("#rows").val(), 10);
  let columns = parseInt($("#columns").val(), 10);
  rows = Math.max(1, Math.min(7, rows));
  columns = Math.max(1, Math.min(7, columns));
  $("#rows").val(rows);
  $("#columns").val(columns);

  if (rows >= 1 && columns >= 1) {
    localStorage.setItem("gridRows", rows);
    localStorage.setItem("gridColumns", columns);
    updateGridAndViewers(rows, columns);
    scaleTimecodeFont();

    $("#viewerSettingsPopOver").removeClass("visible");
    setTimeout(function () {
      $("#viewerSettingsPopOver").css("visibility", "hidden");
    }, 200);
  } else {
    alert("Please enter valid numbers for rows and columns.");
  }
});

$(document).ready(function () {
  let storedRows = parseInt(localStorage.getItem("gridRows"), 10) || 4;
  let storedColumns = parseInt(localStorage.getItem("gridColumns"), 10) || 4;
  storedRows = Math.max(1, Math.min(7, storedRows));
  storedColumns = Math.max(1, Math.min(7, storedColumns));
  $("#rows").val(storedRows);
  $("#columns").val(storedColumns);
  updateGridAndViewers(storedRows, storedColumns);
  window.sourcesLoaded = false;
  scaleTimecodeFont();
});

function updateViewerMaxWidth(maxWidth) {
  document.documentElement.style.setProperty("--viewer-max-width", maxWidth);
}

updateViewerMaxWidth("400px");
$(document).on("click", function (event) {
  if (
    !$(event.target).closest(".destinationsLabel, .destinationsPopOver").length
  ) {
    var popovers = $(".destinationsPopOver.visible");
    popovers.removeClass("visible");
    setTimeout(function () {
      popovers.css("visibility", "hidden");
    }, 200);
  }
});

$("#viewers").off("click", ".destinationsLabel").off("click", "button");

function debugViewerStates() {
  console.log("DEBUG: Checking viewer states");
  for (var i = 0; i < model.viewers().length; i++) {
    var viewer = model.viewers()[i];
    if (viewer.selectedSource()) {
      console.log(
        "Viewer " +
          i +
          " - Selected: " +
          viewer.isSelected() +
          " - Recording: " +
          viewer.isRecording() +
          " - Source Recording: " +
          (viewer.selectedSource()
            ? viewer.selectedSource().isRecording()
            : "N/A")
      );
    }
  }
  setTimeout(debugViewerStates, 2000);
}

$(document).ready(function () {});

$(document).ready(function () {
  var menuHidden = localStorage.getItem("menuHidden") === "true";

  $("#menuToggleButton").on("click", function () {
    $("#left").toggleClass("hidden");
    var isHidden = $("#left").hasClass("hidden");
    $("body").toggleClass("menu-hidden", isHidden);

    localStorage.setItem("menuHidden", isHidden);
    setTimeout(function () {
      resizeGrid();
    }, 300);
  });
});
window.addEventListener("resize", function () {
  clearTimeout(window.resizeTimeout);
  window.resizeTimeout = setTimeout(resizeGrid, 100);
});

function resizeGrid() {
  const rows = parseInt($("#rows").val(), 10) || 4;
  const columns = parseInt($("#columns").val(), 10) || 4;
  updateGridAndViewers(rows, columns);
  scaleTimecodeFont();
}

function scaleTimecodeFont() {
  $(".canvaswrap").each(function () {
    var $wrap = $(this);
    var $timecode = $wrap.find(".timecode");
    var wrapHeight = $wrap.height();
    var availableHeight = wrapHeight * 0.16;
    var fontSize = Math.max(10, availableHeight * 0.5);
    $timecode.css("font-size", fontSize + "px");
    $timecode.css("max-height", availableHeight * 0.95 + "px");
  });
}
function resizeGrid() {
  const rows = parseInt($("#rows").val(), 10) || 4;
  const columns = parseInt($("#columns").val(), 10) || 4;
  updateGridAndViewers(rows, columns);
  scaleTimecodeFont();
}
$("#applyGridSettings")
  .off("click")
  .on("click", function () {
    let rows = parseInt($("#rows").val(), 10);
    let columns = parseInt($("#columns").val(), 10);
    rows = Math.max(1, Math.min(7, rows));
    columns = Math.max(1, Math.min(7, columns));
    $("#rows").val(rows);
    $("#columns").val(columns);

    if (rows >= 1 && columns >= 1) {
      localStorage.setItem("gridRows", rows);
      localStorage.setItem("gridColumns", columns);
      updateGridAndViewers(rows, columns);
      scaleTimecodeFont();

      $("#viewerSettingsPopOver").removeClass("visible");
      setTimeout(function () {
        $("#viewerSettingsPopOver").css("visibility", "hidden");
      }, 200);
    } else {
      alert("Please enter valid numbers for rows and columns.");
    }
  });
$(document).ready(function () {
  let storedRows = parseInt(localStorage.getItem("gridRows"), 10) || 4;
  let storedColumns = parseInt(localStorage.getItem("gridColumns"), 10) || 4;
  storedRows = Math.max(1, Math.min(7, storedRows));
  storedColumns = Math.max(1, Math.min(7, storedColumns));
  $("#rows").val(storedRows);
  $("#columns").val(storedColumns);
  updateGridAndViewers(storedRows, storedColumns);
  window.sourcesLoaded = false;
  scaleTimecodeFont();
});

window.addEventListener("resize", function () {
  clearTimeout(window.resizeTimeout);
  window.resizeTimeout = setTimeout(resizeGrid, 100);
});

$(function () {
  function updateMenuIcon() {
    var isHidden = $("#left").hasClass("hidden");
    $("#menuToggleButton").toggleClass("menu-open", !isHidden);
  }
  updateMenuIcon();
  $("#menuToggleButton").on("click", function () {
    setTimeout(updateMenuIcon, 310);
  });
  $("#calendarButton").on("click", function () {
    const url = `${window.location.protocol}//${window.location.hostname}:${window.location.port}/schedule/index.html`;
    window.open(url, "_blank");
  });
});
