/**
 * DisplaySettings - Block editor display/position controls
 *
 * Adds position controls (default, relative container, absolute overlay)
 * to all blocks with configurable dimensions.
 *
 * Single file by design: no module system available (plain JS, no build step).
 */
(function () {
  var el = wp.element.createElement;
  var Fragment = wp.element.Fragment;
  var useState = wp.element.useState;
  var useEffect = wp.element.useEffect;
  var useRef = wp.element.useRef;
  var useCallback = wp.element.useCallback;
  var __ = wp.i18n.__;
  var addFilter = wp.hooks.addFilter;
  var createHigherOrderComponent = wp.compose.createHigherOrderComponent;
  var InspectorControls = wp.blockEditor.InspectorControls;
  var PanelBody = wp.components.PanelBody;
  var CustomSelectControl = wp.components.CustomSelectControl;
  var Spacer = wp.components.__experimentalSpacer;
  var VStack = wp.components.__experimentalVStack;
  var HStack = wp.components.__experimentalHStack;
  var UnitControl = wp.components.__experimentalUnitControl;
  var useSelect = wp.data.useSelect;

  // ── Position options ────────────────────────────────────────────────

  var positionOptions = [
    { key: "default", name: __("Default", "brandy"), value: "default" },
    {
      key: "relative",
      name: __("Container (relative)", "brandy"),
      value: "relative",
      hint: __(
        "Makes this block a positioning container for overlay children.",
        "brandy"
      ),
    },
    {
      key: "absolute",
      name: __("Overlay (absolute)", "brandy"),
      value: "absolute",
      hint: __(
        "Float this block inside its parent container at an exact position.",
        "brandy"
      ),
    },
  ];

  // ── PositionPicker helpers ──────────────────────────────────────────

  var SNAP_POINTS = [
    { x: 0, y: 0 },
    { x: 0.5, y: 0 },
    { x: 1, y: 0 },
    { x: 0, y: 0.5 },
    { x: 0.5, y: 0.5 },
    { x: 1, y: 0.5 },
    { x: 0, y: 1 },
    { x: 0.5, y: 1 },
    { x: 1, y: 1 },
  ];

  var SNAP_THRESHOLD = 0.07;
  var DOT_SIZE = 14;
  var SNAP_DOT_SIZE = 6;

  function clamp(v, min, max) {
    return Math.min(Math.max(v, min), max);
  }

  function snapToGrid(rawX, rawY) {
    for (var i = 0; i < SNAP_POINTS.length; i++) {
      var p = SNAP_POINTS[i];
      if (
        Math.abs(rawX - p.x) < SNAP_THRESHOLD &&
        Math.abs(rawY - p.y) < SNAP_THRESHOLD
      ) {
        return { x: p.x, y: p.y };
      }
    }
    return { x: rawX, y: rawY };
  }

  function positionToDimensions(x, y) {
    var d = {};
    if (x <= 0.5) d.left = Math.round(x * 100) + "%";
    else d.right = Math.round((1 - x) * 100) + "%";
    if (y <= 0.5) d.top = Math.round(y * 100) + "%";
    else d.bottom = Math.round((1 - y) * 100) + "%";
    return d;
  }

  function dimensionsToPosition(dims) {
    if (!dims) return { x: 0, y: 0 };
    var x = 0;
    var y = 0;

    if (dims.left != null && dims.left !== "") {
      var n = parseFloat(dims.left) || 0;
      x = String(dims.left).includes("%") ? n / 100 : 0;
    } else if (dims.right != null && dims.right !== "") {
      var n = parseFloat(dims.right) || 0;
      x = String(dims.right).includes("%") ? 1 - n / 100 : 1;
    }

    if (dims.top != null && dims.top !== "") {
      var n = parseFloat(dims.top) || 0;
      y = String(dims.top).includes("%") ? n / 100 : 0;
    } else if (dims.bottom != null && dims.bottom !== "") {
      var n = parseFloat(dims.bottom) || 0;
      y = String(dims.bottom).includes("%") ? 1 - n / 100 : 1;
    }

    return { x: clamp(x, 0, 1), y: clamp(y, 0, 1) };
  }

  function getClientPos(e) {
    if (e.touches && e.touches.length > 0) {
      return { clientX: e.touches[0].clientX, clientY: e.touches[0].clientY };
    }
    return { clientX: e.clientX, clientY: e.clientY };
  }

  function getActiveEdges(dimensions) {
    var vertical =
      dimensions &&
      dimensions.bottom != null &&
      dimensions.bottom !== "" &&
      !dimensions.top
        ? "bottom"
        : "top";
    var horizontal =
      dimensions &&
      dimensions.right != null &&
      dimensions.right !== "" &&
      !dimensions.left
        ? "right"
        : "left";
    return { vertical: vertical, horizontal: horizontal };
  }

  // ── Spacing preset helper ──────────────────────────────────────────

  function getSpacingPresetCssVar(value) {
    if (!value) return;
    var slug = value.match(/var:preset\|spacing\|(.+)/);
    if (!slug) return value;
    return "var(--wp--preset--spacing--" + slug[1] + ")";
  }

  // ── PositionPicker component ────────────────────────────────────────

  function PositionPicker(props) {
    var dimensions = props.dimensions;
    var onChange = props.onChange;
    var aspectRatio = props.aspectRatio || 4 / 3;

    var ref = useRef(null);
    var draggingState = useState(false);
    var dragging = draggingState[0];
    var setDragging = draggingState[1];
    var dragPosState = useState(null);
    var dragPos = dragPosState[0];
    var setDragPos = dragPosState[1];

    var pos = dragPos || dimensionsToPosition(dimensions);

    var calcPosition = useCallback(
      function (e) {
        var rect = ref.current && ref.current.getBoundingClientRect();
        if (!rect) return;
        var cp = getClientPos(e);
        var rawX = clamp((cp.clientX - rect.left) / rect.width, 0, 1);
        var rawY = clamp((cp.clientY - rect.top) / rect.height, 0, 1);
        var snapped = snapToGrid(rawX, rawY);
        setDragPos(snapped);
        onChange(positionToDimensions(snapped.x, snapped.y));
      },
      [onChange]
    );

    var onDown = useCallback(
      function (e) {
        e.preventDefault();
        setDragging(true);
        calcPosition(e);

        var move = function (ev) {
          ev.preventDefault();
          calcPosition(ev);
        };
        var up = function () {
          setDragging(false);
          setDragPos(null);
          window.removeEventListener("mousemove", move);
          window.removeEventListener("mouseup", up);
          window.removeEventListener("touchmove", move);
          window.removeEventListener("touchend", up);
        };

        window.addEventListener("mousemove", move);
        window.addEventListener("mouseup", up);
        window.addEventListener("touchmove", move, { passive: false });
        window.addEventListener("touchend", up);
      },
      [calcPosition]
    );

    var snapDots = SNAP_POINTS.map(function (p, i) {
      return el("div", {
        key: i,
        style: {
          position: "absolute",
          left: "calc(" + p.x * 100 + "% - " + SNAP_DOT_SIZE / 2 + "px)",
          top: "calc(" + p.y * 100 + "% - " + SNAP_DOT_SIZE / 2 + "px)",
          width: SNAP_DOT_SIZE,
          height: SNAP_DOT_SIZE,
          borderRadius: "50%",
          backgroundColor: "#ccc",
          pointerEvents: "none",
        },
      });
    });

    var activeDot = el("div", {
      style: {
        position: "absolute",
        left: "calc(" + pos.x * 100 + "% - " + DOT_SIZE / 2 + "px)",
        top: "calc(" + pos.y * 100 + "% - " + DOT_SIZE / 2 + "px)",
        width: DOT_SIZE,
        height: DOT_SIZE,
        borderRadius: "50%",
        backgroundColor: "var(--wp-admin-theme-color, #007cba)",
        border: "2px solid #fff",
        boxShadow: "0 1px 3px rgba(0,0,0,0.3)",
        pointerEvents: "none",
        transition: dragging ? "none" : "all 0.15s ease",
        zIndex: 1,
      },
    });

    return el(
      "div",
      {
        ref: ref,
        onMouseDown: onDown,
        onTouchStart: onDown,
        style: {
          position: "relative",
          width: "100%",
          aspectRatio: aspectRatio,
          border: "1px solid #e0e0e0",
          borderRadius: "4px",
          backgroundColor: "#f0f0f0",
          cursor: dragging ? "grabbing" : "crosshair",
          userSelect: "none",
          touchAction: "none",
          height: 200
        },
      },
      snapDots.concat([activeDot])
    );
  }

  // ── DisplaySettings panel component ─────────────────────────────────

  function DisplaySettingsPanel(props) {
    var attributes = props.attributes;
    var setAttributes = props.setAttributes;
    var clientId = props.clientId;

    var displaySettings = attributes.displaySettings || {};
    var key = displaySettings.key;
    var dimensions = displaySettings.dimensions;
    var width = displaySettings.width;
    var height = displaySettings.height;

    var parentClientId = useSelect(
      function (select) {
        var parents = select("core/block-editor").getBlockParents(clientId);
        return parents.length > 0 ? parents[parents.length - 1] : null;
      },
      [clientId]
    );

    var aspectState = useState(4 / 3);
    var parentAspectRatio = aspectState[0];
    var setParentAspectRatio = aspectState[1];

    useEffect(
      function () {
        if (!parentClientId) return;
        var domEl = document.querySelector(
          '[data-block="' + parentClientId + '"]'
        );
        if (domEl) {
          var rect = domEl.getBoundingClientRect();
          if (rect.width > 0 && rect.height > 0) {
            setParentAspectRatio(rect.width / rect.height);
          }
        }
      },
      [parentClientId]
    );

    function updateDisplaySettings(updates) {
      var merged = Object.assign({}, displaySettings, updates);
      setAttributes({ displaySettings: merged });
    }

    var edges = getActiveEdges(dimensions);

    var absoluteControls = null;
    if (key === "absolute") {
      absoluteControls = el(
        Spacer,
        { marginTop: 10 },
        el(
          VStack,
          { spacing: 3 },
          // Position picker
          el(
            "div",
            null,
            el(
              "span",
              {
                style: {
                  display: "block",
                  marginBottom: 6,
                  fontSize: 11,
                  color: "#757575",
                  textTransform: "uppercase",
                  fontWeight: 500,
                },
              },
              __("Position", "brandy")
            ),
            el(PositionPicker, {
              dimensions: dimensions,
              aspectRatio: parentAspectRatio,
              onChange: function (newDimensions) {
                updateDisplaySettings({ dimensions: newDimensions });
              },
            })
          ),
          // Top/Bottom + Left/Right
          el(
            HStack,
            { alignment: "top" },
            el(UnitControl, {
              label:
                edges.vertical === "top"
                  ? __("Top", "brandy")
                  : __("Bottom", "brandy"),
              onChange: function (value) {
                var edge = getActiveEdges(dimensions).vertical;
                var opposite = edge === "top" ? "bottom" : "top";
                var newDims = Object.assign({}, dimensions);
                newDims[edge] = value;
                delete newDims[opposite];
                updateDisplaySettings({ dimensions: newDims });
              },
              value:
                edges.vertical === "top"
                  ? (dimensions && dimensions.top) || "0%"
                  : (dimensions && dimensions.bottom) || "0%",
              step: 1,
            }),
            el(UnitControl, {
              label:
                edges.horizontal === "left"
                  ? __("Left", "brandy")
                  : __("Right", "brandy"),
              onChange: function (value) {
                var edge = getActiveEdges(dimensions).horizontal;
                var opposite = edge === "left" ? "right" : "left";
                var newDims = Object.assign({}, dimensions);
                newDims[edge] = value;
                delete newDims[opposite];
                updateDisplaySettings({ dimensions: newDims });
              },
              value:
                edges.horizontal === "left"
                  ? (dimensions && dimensions.left) || "0%"
                  : (dimensions && dimensions.right) || "0%",
              step: 1,
            })
          ),
          // Width + Height
          el(
            HStack,
            { alignment: "top" },
            el(UnitControl, {
              label: __("Width", "brandy"),
              max: 1000,
              min: 0,
              onChange: function (value) {
                updateDisplaySettings({ width: value });
              },
              step: 1,
              value: width || "40px",
            }),
            el(UnitControl, {
              label: __("Height", "brandy"),
              max: 1000,
              min: 0,
              onChange: function (value) {
                updateDisplaySettings({ height: value });
              },
              step: 1,
              value: height,
            })
          )
        )
      );
    }

    return el(
      InspectorControls,
      null,
      el(
        PanelBody,
        { title: __("Display", "brandy") },
        el(CustomSelectControl, {
          options: positionOptions,
          value: displaySettings,
          __next40pxDefaultSize: true,
          onChange: function (value) {
            var item = value.selectedItem;
            updateDisplaySettings({
              key: item ? item.value : "default",
              name: item ? item.name : "Default",
            });
          },
        }),
        absoluteControls
      )
    );
  }

  // ── Register attribute ──────────────────────────────────────────────

  addFilter(
    "blocks.registerBlockType",
    "brandy/display-settings-attributes",
    function (settings) {
      if (typeof settings.attributes === "undefined") {
        return settings;
      }
      settings.attributes = Object.assign(settings.attributes, {
        displaySettings: {
          type: "object",
          default: { key: "default", name: "Default" },
        },
      });
      return settings;
    }
  );

  // ── Add controls to inspector ───────────────────────────────────────

  addFilter(
    "editor.BlockEdit",
    "brandy/display-settings-controls",
    createHigherOrderComponent(function (BlockEdit) {
      return function (props) {
        return el(
          Fragment,
          null,
          el(BlockEdit, props),
          props.isSelected &&
            el(DisplaySettingsPanel, {
              attributes: props.attributes,
              setAttributes: props.setAttributes,
              clientId: props.clientId,
            })
        );
      };
    }, "displaySettingsControls")
  );

  // ── Add editor preview styles ───────────────────────────────────────

  addFilter(
    "editor.BlockListBlock",
    "brandy/display-settings-style",
    createHigherOrderComponent(function (BlockListBlock) {
      return function (props) {
        var ds = (props.attributes && props.attributes.displaySettings) || {};
        var dsKey = ds.key;
        var dsDimensions = ds.dimensions;
        var dsWidth = ds.width;
        var dsHeight = ds.height;

        var wrapperProps = Object.assign({}, props.wrapperProps || {});

        if (wrapperProps.style == null) {
          wrapperProps.style = {};
        } else {
          wrapperProps.style = Object.assign({}, wrapperProps.style);
        }

        if (wrapperProps.className == null) {
          wrapperProps.className = "";
        }

        if (dsKey === "default" || !dsKey) {
          return el(BlockListBlock, props);
        }

        wrapperProps.className += " is-" + dsKey + "-position ";

        if (dsDimensions && dsDimensions.top) {
          wrapperProps.style["--top"] = getSpacingPresetCssVar(
            dsDimensions.top
          );
        }
        if (dsDimensions && dsDimensions.bottom) {
          wrapperProps.style["--bottom"] = getSpacingPresetCssVar(
            dsDimensions.bottom
          );
        }
        if (dsDimensions && dsDimensions.left) {
          wrapperProps.style["--left"] = getSpacingPresetCssVar(
            dsDimensions.left
          );
        }
        if (dsDimensions && dsDimensions.right) {
          wrapperProps.style["--right"] = getSpacingPresetCssVar(
            dsDimensions.right
          );
        }

        if (dsKey === "absolute") {
          wrapperProps.style["--width"] = dsWidth || "";
          wrapperProps.style["--height"] = dsHeight || "";
        }

        return el(
          BlockListBlock,
          Object.assign({}, props, { wrapperProps: wrapperProps })
        );
      };
    }, "addDisplaySettingsStyle")
  );
})();
