import { MainPanel } from "../types/index.js";

const SETTINGS_KEY = "status-area-h-padding";
const PANEL_BUTTON_CLASS = "panel-button";
const LAYOUT_REFRESH_CLASS = "veil-hspacing-layout-refresh-dummy";


function buildPaddingStyle(paddingPx) {
  let line = `-natural-hpadding: ${paddingPx}px`;
  if (paddingPx < 6) {
    line += `; -minimum-hpadding: ${paddingPx}px`;
  }
  return line;
}

function mergeWithBaseline(paddingStyle, baseline) {
  return baseline.length > 0 ? `${paddingStyle}; ${baseline}` : paddingStyle;
}

function resolvePanelButton(container) {
  const widget = container;
  if (widget.has_style_class_name?.(PANEL_BUTTON_CLASS)) {
    return widget;
  }
  const children = container.get_children();
  if (children.length === 0) {
    return null;
  }
  const first = children[0];
  return first.has_style_class_name?.(PANEL_BUTTON_CLASS) ? first : null;
}

function refreshPanelButtonLayout(button) {
  const previous = button.get_style_class_name() ?? "";
  button.set_style_class_name(LAYOUT_REFRESH_CLASS);
  button.set_style_class_name(previous);
}

class StatusAreaHorizontalSpacing {
  settings;
  paddingStyle;
  settingsHandlerId = null;
  childAddedId = null;
  tracked = /* @__PURE__ */ new Map();

  constructor(settings) {
    this.settings = settings;
    this.paddingStyle = buildPaddingStyle(settings.get_int(SETTINGS_KEY));
  }

  enable() {
    for (const child of MainPanel._rightBox.get_children()) {
      this.attachToContainer(child);
    }

    this.childAddedId = MainPanel._rightBox.connect(
      "child-added",
      (_box, actor) => {
        this.attachToContainer(actor);
      }
    );

    this.settingsHandlerId = this.settings.connect(
      `changed::${SETTINGS_KEY}`,
      () => {
        this.paddingStyle = buildPaddingStyle(
          this.settings.get_int(SETTINGS_KEY)
        );
        this.reapplyAll();
      }
    );
  }

  destroy() {
    if (this.settingsHandlerId !== null) {
      this.settings.disconnect(this.settingsHandlerId);
      this.settingsHandlerId = null;
    }
    if (this.childAddedId !== null) {
      MainPanel._rightBox.disconnect(this.childAddedId);
      this.childAddedId = null;
    }
    for (const child of MainPanel._rightBox.get_children()) {
      this.detachFromContainer(child);
    }
    this.tracked.clear();
  }

  reapplyAll() {
    for (const child of MainPanel._rightBox.get_children()) {
      this.detachFromContainer(child);
      this.attachToContainer(child);
    }
  }

  attachToContainer(container) {
    const button = resolvePanelButton(container);
    if (!button || this.tracked.has(button)) {
      return;
    }
    const baselineStyle = button.get_style() ?? "";
    this.wireButton(button, baselineStyle);
  }

  wireButton(button, baselineStyle) {
    button.set_style(mergeWithBaseline(this.paddingStyle, baselineStyle));

    const styleChangedId = button.connect("style-changed", () => {
      const current = button.get_style() ?? "";
      if (current.includes(this.paddingStyle)) {
        return;
      }
      button.disconnect(styleChangedId);
      this.tracked.delete(button);
      this.wireButton(button, current);
    });

    this.tracked.set(button, { baselineStyle, styleChangedId });
    refreshPanelButtonLayout(button);
  }

  detachFromContainer(container) {
    const button = resolvePanelButton(container);
    if (!button) {
      return;
    }
    const entry = this.tracked.get(button);
    if (!entry) {
      return;
    }
    button.disconnect(entry.styleChangedId);
    button.set_style(entry.baselineStyle);
    this.tracked.delete(button);
    refreshPanelButtonLayout(button);
  }
}

export {
  StatusAreaHorizontalSpacing
};
