internal/dashboard/frontend/src/utils/chart.ts

import { useChartStore } from "src/store";

type RGB = { r: number; g: number; b: number };

const colors: RGB[] = [
  { r: 163, g: 230, b: 53 }, // Lime
  { r: 250, g: 204, b: 21 }, // Yellow
  { r: 251, g: 191, b: 36 }, // Amber
  { r: 251, g: 146, b: 60 }, // Orange
  { r: 239, g: 68, b: 68 }, // Red
] as const;

export const colorscale: [number, string][] = colors.map((color, index) => [
  index / (colors.length - 1),
  `rgb(${color.r},${color.g},${color.b})`,
]);

export function getCalculatedColor(index: number, total: number): string {
  if (total <= 1) {
    const color = colors[0];
    if (!color) return "#ff6900";
    return `rgb(${color.r},${color.g},${color.b})`;
  }

  const ratio = index / (total - 1);
  const scaledRatio = ratio * (colors.length - 1);
  const i = Math.floor(scaledRatio);
  const f = scaledRatio - i;

  const c1 = colors[i];
  const c2 = colors[Math.min(i + 1, colors.length - 1)];

  if (!c1 || !c2) {
    return "#ff6900";
  }

  const r = Math.round(c1.r + (c2.r - c1.r) * f);
  const g = Math.round(c1.g + (c2.g - c1.g) * f);
  const b = Math.round(c1.b + (c2.b - c1.b) * f);

  return `rgb(${r},${g},${b})`;
}

export const hoverlabel = {
  bgcolor: "#292524",
  font: { color: "#d6d3d1", size: 12 },
  bordercolor: "#44403c",
};

export const gridcolor = "#292524";
export const tickfontcolor = "#a8a29e";
export const selectedColor = "#ff6900";
export const spikecolor = "rgba(245, 158, 11, 0.7)";

// Map specific
export const mapCoastlineColor = "#f59e0b55";
export const mapCountryColor = "#f59e0baa";
export const mapLandColor = "#f59e0b22";
export const mapOceanColor = "#0c0a0955";
export const mapMarkerLineColor = "rgba(255, 255, 255, 0.5)";
export const mapMarkerLineWidth = 0.5;

// Font sizes
export const labelFontSize = 12;

// Margins
export const defaultChartMargin: Partial<Plotly.Margin> = {
  t: 30,
  b: 60,
  l: 80,
  r: 30,
};
export const categoricalChartMargin: Partial<Plotly.Margin> = {
  t: 30,
  b: 60,
  l: 120,
  r: 30,
};
export const activityChartMargin: Partial<Plotly.Margin> = {
  t: 20,
  b: 40,
  l: 50,
  r: 20,
};
export const mapChartMargin: Partial<Plotly.Margin> = {
  l: 0,
  r: 0,
  t: 0,
  b: 0,
  pad: 0,
};

// Modebar
export const modebar: Partial<Plotly.ModeBar> = {
  bgcolor: "#1c1917",
  activecolor: "#fbbf24",
  color: "#a8a29e",
};

// Marker sizes
export const defaultMarkerSize = 6;
export const selectedMarkerSize = 7;
export const unselectedMarkerSize = 4;
export const unselectedOpacity = 0.5;
export const mapMarkerBaseSize = 6;
export const mapMarkerScaleFactor = 12;

// Port constraints
export const portMaxAllowed = 70000;
export const portMinAllowed = -5000;

// Sidebar
export const sidebarLimit = 50;

// Activity
export const activityDataLimit = 10000;

export function excludeIP(ip: string) {
  const chartStore = useChartStore();
  const excluded = chartStore.state.remote_addr.includes("!" + ip);
  if (excluded) {
    chartStore.state.remote_addr = chartStore.state.remote_addr.filter(
      (a) => a !== "!" + ip,
    );
  } else {
    chartStore.state.remote_addr = [...chartStore.state.remote_addr, "!" + ip];
  }
}

export function excludeCountry(country: string) {
  const chartStore = useChartStore();
  const countryStr = `!${country}`;
  const currentCountries = chartStore.state.country || [];
  if (!currentCountries.includes(countryStr)) {
    chartStore.state.country = [...currentCountries, countryStr];
  }
}

export function excludePort(port: number) {
  const chartStore = useChartStore();
  const portStr = `!${port}`;
  const currentPorts = chartStore.state.dst_port || [];

  if (!currentPorts.includes(portStr)) {
    chartStore.state.dst_port = [...currentPorts, portStr];
  }
}