import { unsafeCSS, LitElement, svg, nothing, html } from "lit";
import { property, state } from "lit/decorators.js";
import { circle } from "../../svghelpers/circle.js";
import { getSetpointAnimationDurationMs, deriveRadialSetpointConfig, RADIAL_SETPOINT_RADIUS, drawSetpointMarker, cssSafeAngle, SETPOINT_ANIMATION_CSS_VAR, SETPOINT_ANIMATION_DURATION_DEFAULT, getSetpointOutwardOffset, SetpointVisualState } from "../../svghelpers/setpoint.js";
import { roundedArch } from "../../svghelpers/roundedArch.js";
import { InstrumentState, Priority } from "../types.js";
import compentStyle from "./watch.css.js";
import { ResizeController } from "@lit-labs/observers/resize-controller.js";
import { renderAdvice, adviceMask } from "./advice.js";
import { TickmarkStyle, tickmark } from "./tickmark.js";
import { RotPosition, RotType, shortestAngularDeltaDeg, renderRotBarStatic, renderRotBarDots, renderRotDots } from "../rate-of-turn/rot-renderer.js";
import { disposeRotController, RateOfTurnController } from "../rate-of-turn/rate-of-turn.controller.js";
import { getLabelPositions, renderLabels, renderNorthArrow } from "./label.js";
import { VesselImageSize, vesselImages } from "./vessel.js";
import { VesselImage } from "./vessel.js";
import { renderWind, renderCurrent } from "./environment.js";
import { customElement } from "../../decorator.js";
import { computeZoomToFitArcFrame } from "../../svghelpers/arc-frame.js";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result) __defProp(target, key, result);
  return result;
};
var WatchCircleType = /* @__PURE__ */ ((WatchCircleType2) => {
  WatchCircleType2["single"] = "single";
  WatchCircleType2["double"] = "double";
  WatchCircleType2["doubleThin"] = "doubleThin";
  WatchCircleType2["triple"] = "triple";
  return WatchCircleType2;
})(WatchCircleType || {});
const OUTER_RING_RADIUS = 368 / 2;
const RING2_RADIUS = 320 / 2;
const RING3_RADIUS = 224 / 2;
const RING3B_RADIUS = 272 / 2;
const RING4_RADIUS = 176 / 2;
function innerRingRadiusFor(type) {
  switch (type) {
    case "single":
      return RING2_RADIUS;
    case "double":
      return RING3_RADIUS;
    case "doubleThin":
      return RING3B_RADIUS;
    case "triple":
      return RING4_RADIUS;
    default:
      throw new Error(`Unknown WatchCircleType: ${type}`);
  }
}
const RADIAL_SETPOINT_INWARD_ADJUST = 4;
let ObcWatch = class extends LitElement {
  constructor() {
    super(...arguments);
    this._setpointId = `watch-setpoint-${Math.random().toString(36).slice(2, 9)}`;
    this._newSetpointId = `watch-new-setpoint-${Math.random().toString(36).slice(2, 9)}`;
    this.state = InstrumentState.active;
    this.priority = Priority.regular;
    this.watchCircleType = "single";
    this.northArrow = false;
    this.atAngleSetpoint = false;
    this.angleSetpointAtZeroDeadband = 0.5;
    this.setpointOverride = false;
    this.touching = false;
    this.animateSetpoint = false;
    this._setpointCssAngle = 0;
    this._setpointCssAngleInit = false;
    this.areas = [];
    this.barAreas = [];
    this.needles = [];
    this.tickmarks = [];
    this.tickmarksInside = false;
    this.tickmarkStyle = TickmarkStyle.regular;
    this.advices = [];
    this.crosshairEnabled = false;
    this.showLabels = false;
    this.vessels = [];
    this.wind = null;
    this.windFromDirectionDeg = null;
    this.windSymbolRadius = null;
    this.current = null;
    this.currentFromDirectionDeg = null;
    this.currentSymbolRadius = null;
    this.starboardPortIndicator = false;
    this.clipTop = 0;
    this.clipBottom = 0;
    this.scaleWindIcon = 1;
    this.zoomToFitArc = false;
    this.tickFadeAngle = 0;
    this.rotPosition = RotPosition.innerCircle;
    this.rotStartAngle = 0;
    this.rotEndAngle = 0;
    this._rotationsPerMinute = 0;
    this._resizeController = new ResizeController(this, {});
    this._rOff = 0;
  }
  set rotationsPerMinute(value) {
    this._rotationsPerMinute = value;
    if (this._rotController) {
      this._rotController.rotationsPerMinute = value;
    }
  }
  get rotationsPerMinute() {
    return this._rotationsPerMinute;
  }
  willUpdate(changed) {
    super.willUpdate(changed);
    if (changed.has("newAngleSetpoint") && this.animateSetpoint) {
      const prev = changed.get("newAngleSetpoint");
      if (prev !== void 0 && this.newAngleSetpoint === void 0) {
        this._departingNewAngleSetpoint = prev;
        clearTimeout(this._animationTimer);
        const duration = getSetpointAnimationDurationMs(this);
        this._animationTimer = setTimeout(() => {
          this._departingNewAngleSetpoint = void 0;
        }, duration);
      }
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    clearTimeout(this._animationTimer);
    this._rotController = disposeRotController(this, this._rotController);
  }
  updated(changed) {
    super.updated(changed);
    const el = this.rotType ? this.renderRoot.querySelector("#rot-spinner") : null;
    if (!el) {
      this._rotController = disposeRotController(this, this._rotController);
      return;
    }
    if (!this._rotController || this._rotController.el !== el) {
      this._rotController = disposeRotController(this, this._rotController);
      this._rotController = new RateOfTurnController(
        this,
        el,
        this._rotationsPerMinute
      );
    }
  }
  get innerRingRadius() {
    return innerRingRadiusFor(this.watchCircleType);
  }
  watchCircle() {
    const rings = [];
    if (this.state !== InstrumentState.off) {
      rings.push(svg`
        <circle
          cx="0"
          cy="0"
          r="${172 + this._rOff}"
          stroke="var(--instrument-frame-primary-color)"
          fill="none"
          stroke-width="24"
        />`);
      if (this.watchCircleType !== "single") {
        const r1 = RING2_RADIUS + this._rOff;
        const r2 = (this.watchCircleType === "doubleThin" ? RING3B_RADIUS : RING3_RADIUS) + this._rOff;
        const r = (r1 + r2) / 2;
        const strokeWidth = r1 - r2;
        rings.push(
          svg`
            <circle cx="0" cy="0" r=${r} stroke="var(--instrument-frame-secondary-color)" stroke-width=${strokeWidth} fill="none" />
            <circle cx="0" cy="0" r=${r1} stroke="var(--instrument-frame-secondary-color)" stroke-width="1" fill="none" vector-effect="non-scaling-stroke" />
            <circle cx="0" cy="0" r=${r2} stroke="var(--instrument-frame-secondary-color)" stroke-width="1" fill="none" vector-effect="non-scaling-stroke" />
        `
        );
      }
      if (this.watchCircleType === "triple") {
        const r1 = RING3_RADIUS + this._rOff;
        const r2 = RING4_RADIUS + this._rOff;
        const r = (r1 + r2) / 2;
        const strokeWidth = r1 - r2;
        rings.push(
          svg`<circle cx="0" cy="0" r=${r} stroke="var(--instrument-frame-primary-color)" stroke-width=${strokeWidth} fill="none" />`
        );
      }
    }
    const maskSize = Math.max(200, OUTER_RING_RADIUS + this._rOff + 50);
    let result = rings;
    if (this.areas.length > 0) {
      const areas = this.areas.map((area) => {
        const svgPath = roundedArch({
          startAngle: area.startAngle,
          endAngle: area.endAngle,
          R: OUTER_RING_RADIUS + this._rOff,
          r: this.innerRingRadius + this._rOff,
          roundOutsideCut: area.roundOutsideCut,
          roundInsideCut: area.roundInsideCut
        });
        return svgPath;
      });
      const mask = svg`<mask id="cutMask">
        <rect x="${-maskSize}" y="${-maskSize}" width="${maskSize * 2}" height="${maskSize * 2}" fill="black" />
        ${areas.map((area) => svg`<path d=${area} fill="white" vector-effect="non-scaling-stroke" stroke="white" stroke-width="1"/>`)}
      </mask>`;
      const rotClip = svg`<clipPath id="rot-arc-clip">${this.areas.map(
        (area) => svg`<path d=${roundedArch({
          startAngle: area.startAngle,
          endAngle: area.endAngle,
          R: OUTER_RING_RADIUS + this._rOff + 20,
          r: 0,
          roundOutsideCut: area.roundOutsideCut,
          roundInsideCut: area.roundInsideCut
        })} />`
      )}</clipPath>`;
      result = [mask, rotClip, svg`<g mask="url(#cutMask)">${rings}</g>`];
      areas.forEach((area) => {
        result.push(
          svg`<path d=${area} fill="none" stroke="var(--instrument-frame-tertiary-color)" vector-effect="non-scaling-stroke"/>`
        );
      });
    } else {
      if (this.state !== InstrumentState.off) {
        result.push(
          circle("outerRing", {
            radius: OUTER_RING_RADIUS + this._rOff,
            strokeWidth: 1,
            strokeColor: "var(--instrument-frame-tertiary-color)",
            strokePosition: "center",
            fillColor: "none"
          })
        );
        result.push(svg`
          ${circle("innerRing", {
          radius: this.innerRingRadius + this._rOff,
          strokeWidth: 1,
          strokeColor: "var(--instrument-frame-tertiary-color)",
          strokePosition: "center",
          fillColor: "none"
        })}
        `);
      } else {
        result.push(svg`
          ${circle("innerRing", {
          radius: OUTER_RING_RADIUS + this._rOff,
          strokeWidth: 1,
          strokeColor: "var(--instrument-frame-tertiary-color)",
          strokePosition: "center",
          fillColor: "none"
        })}
        `);
      }
    }
    return result;
  }
  _renderTickFadeDefs() {
    if (this.tickFadeAngle <= 0 || this.areas.length === 0) return nothing;
    const area = this.areas[0];
    const arcSpan = area.endAngle - area.startAngle;
    const fade = Math.min(this.tickFadeAngle, arcSpan / 4);
    if (fade < 0.5) return nothing;
    const { startAngle, endAngle } = area;
    const R = OUTER_RING_RADIUS + this._rOff + 200;
    const toRad = (deg) => deg * Math.PI / 180;
    const px = (deg) => R * Math.sin(toRad(deg));
    const py = (deg) => -R * Math.cos(toRad(deg));
    const pieSlice = (a, b) => {
      const x1 = px(a), y1 = py(a);
      const x2 = px(b), y2 = py(b);
      const largeArc = b - a > 180 ? 1 : 0;
      return `M 0 0 L ${x1} ${y1} A ${R} ${R} 0 ${largeArc} 1 ${x2} ${y2} Z`;
    };
    const Rm = (OUTER_RING_RADIUS + this.innerRingRadius) / 2 + this._rOff;
    const gx = (deg) => Rm * Math.sin(toRad(deg));
    const gy = (deg) => -Rm * Math.cos(toRad(deg));
    return svg`
      <defs>
        <linearGradient id="tickFadeL" gradientUnits="userSpaceOnUse"
          x1="${gx(startAngle)}" y1="${gy(startAngle)}"
          x2="${gx(startAngle + fade)}" y2="${gy(startAngle + fade)}">
          <stop offset="0" stop-color="black" />
          <stop offset="1" stop-color="white" />
        </linearGradient>
        <linearGradient id="tickFadeR" gradientUnits="userSpaceOnUse"
          x1="${gx(endAngle - fade)}" y1="${gy(endAngle - fade)}"
          x2="${gx(endAngle)}" y2="${gy(endAngle)}">
          <stop offset="0" stop-color="white" />
          <stop offset="1" stop-color="black" />
        </linearGradient>
        <mask id="tickFadeMask" maskUnits="userSpaceOnUse"
          x="${-R}" y="${-R}" width="${R * 2}" height="${R * 2}">
          <path d="${pieSlice(startAngle + fade, endAngle - fade)}" fill="white" />
          <path d="${pieSlice(startAngle, startAngle + fade)}" fill="url(#tickFadeL)" />
          <path d="${pieSlice(endAngle - fade, endAngle)}" fill="url(#tickFadeR)" />
        </mask>
      </defs>
    `;
  }
  renderCrosshair(radius, labelKnockouts) {
    const hasMask = labelKnockouts && labelKnockouts.positions.length > 0;
    const labelRadius = hasMask ? Math.max(
      ...labelKnockouts.positions.map(
        (l) => Math.abs(l.x !== 0 ? l.x : l.y)
      )
    ) : 0;
    const ringGapPad = hasMask ? 3 / labelKnockouts.scale : 0;
    return svg`
      ${hasMask ? svg`
        <defs>
          <mask
            id="crosshair-label-mask"
            maskUnits="userSpaceOnUse"
            x="-${radius}" y="-${radius}"
            width="${radius * 2}" height="${radius * 2}"
          >
            <rect x="-${radius}" y="-${radius}" width="${radius * 2}" height="${radius * 2}" fill="white"/>
            <!-- Annular ring knockout: hide crosshair between labels and inner ring -->
            <circle cx="0" cy="0" r="${labelKnockouts.innerRingRadius}" fill="black"/>
            <circle cx="0" cy="0" r="${labelRadius - ringGapPad}" fill="white"/>
            <!-- Per-label rectangular knockouts -->
            ${labelKnockouts.positions.map((l) => {
      const fontSize = 12 / labelKnockouts.scale;
      const pad = 3 / labelKnockouts.scale;
      const size = fontSize + pad * 2;
      return svg`
                <rect
                  x="${l.x - size / 2}" y="${l.y - size / 2}"
                  width="${size}" height="${size}"
                  fill="black"
                  transform="rotate(${-(labelKnockouts.rotation ?? 0)})"
                  transform-origin="${l.x} ${l.y}"
                />
              `;
    })}
          </mask>
        </defs>` : nothing}
      <g mask=${hasMask ? "url(#crosshair-label-mask)" : nothing}>
        <line
          x1="-${radius}"
          y1="0"
          x2="${radius}"
          y2="0"
          stroke="var(--instrument-frame-tertiary-color)"
          stroke-width="1"
          vector-effect="non-scaling-stroke"
        />
        <line
          x1="0"
          y1="-${radius}"
          x2="0"
          y2="${radius}"
          stroke="var(--instrument-frame-tertiary-color)"
          stroke-width="1"
          vector-effect="non-scaling-stroke"
        />
      </g>
    `;
  }
  renderBars() {
    if (this.barAreas.length === 0) {
      return nothing;
    }
    return this.barAreas.map((bar, index) => {
      const startAngle = Math.min(bar.startAngle, bar.endAngle);
      const endAngle = Math.max(bar.startAngle, bar.endAngle);
      const arc = roundedArch({
        r: RING3_RADIUS + this._rOff,
        R: RING2_RADIUS + this._rOff,
        startAngle,
        endAngle,
        roundInsideCut: false,
        roundOutsideCut: false
      });
      const barMaskR = RING2_RADIUS + this._rOff + 40;
      const mask = svg`<mask id="barMask-${index}">
        <rect x="${-barMaskR}" y="${-barMaskR}" width="${barMaskR * 2}" height="${barMaskR * 2}" fill="black" />
        <path d=${roundedArch({
        r: 1,
        R: barMaskR,
        startAngle,
        endAngle,
        roundInsideCut: false,
        roundOutsideCut: false
      })} fill="white" />
      </mask>`;
      return svg`
        ${mask}
        <g mask="url(#cutMask)">
        <path 
          d=${arc} 
          fill=${bar.fillColor} 
          stroke=${bar.fillColor} 
          stroke-width="1" 
          vector-effect="non-scaling-stroke" 
          mask="url(#barMask-${index})" 
          />
          </g>
          `;
    });
  }
  renderNeedles() {
    if (this.needles.length === 0) {
      return nothing;
    }
    return this.needles.map((needle) => {
      return svg`
        <rect 
          transform="rotate(${needle.angle})" 
          x="-4" y="${-(RING2_RADIUS + this._rOff)}" width="8" height="48" rx="4" 
          fill=${needle.fillColor} 
          stroke=${needle.strokeColor}
          stroke-width="1"
          vector-effect="non-scaling-stroke"
          paint-order="stroke fill"
        />
      `;
    });
  }
  getScale({ width, height }) {
    let clientWidth = this.clientWidth;
    let clientHeight = this.clientHeight;
    if (clientWidth === 0 || clientHeight === 0) {
      const box = this.parentElement?.getBoundingClientRect();
      if (box) {
        clientWidth = box.width;
        clientHeight = box.height;
      }
    }
    const scale = Math.min(clientWidth / width, clientHeight / height);
    if (scale === Infinity || scale < 0) {
      throw new Error("Watch scale is not valid");
    }
    return scale;
  }
  getPadding() {
    if (this.padding !== void 0) {
      return this.padding;
    }
    const hasTickmarksWithText = this.tickmarks.length > 0 && this.tickmarks.some((t) => t.text !== void 0);
    if (hasTickmarksWithText && !this.tickmarksInside) {
      return 24 * 2.5;
    }
    return 24;
  }
  render() {
    let width;
    let height;
    let viewBox;
    if (this.arcFrame) {
      this._rOff = this.arcFrame.radiusOffset;
      width = this.arcFrame.width;
      height = this.arcFrame.height;
      viewBox = this.arcFrame.viewBox;
    } else if (this.zoomToFitArc && this.areas.length > 0) {
      const ext = this.getPadding();
      const targetSize = (176 + ext) * 2;
      const frame = computeZoomToFitArcFrame({
        areas: this.areas,
        outerRadius: OUTER_RING_RADIUS,
        innerRadius: this.innerRingRadius,
        extension: ext,
        targetSize
      });
      this._rOff = frame.radiusOffset;
      width = frame.width;
      height = frame.height;
      viewBox = frame.viewBox;
    } else {
      this._rOff = 0;
      width = (176 + this.getPadding()) * 2;
      height = width * (1 - this.clipTop / 100 - this.clipBottom / 100);
      const top = -width / 2 + width * this.clipTop / 100;
      viewBox = `-${width / 2} ${top} ${width} ${height}`;
    }
    const rOff = this._rOff;
    const scale = this.getScale({ width, height });
    const angleSetpoint = this.renderSetpoint();
    const textRadius = (this.tickmarksInside ? this.innerRingRadius : OUTER_RING_RADIUS) + rOff;
    const maxDigits = Math.max(
      ...this.tickmarks.map((t) => t.text?.length ?? 0)
    );
    const tickmarks = this.tickmarks.map(
      (t) => tickmark(t.angle, {
        size: t.type,
        style: this.tickmarkStyle,
        scale,
        text: this.showLabels ? void 0 : t.text,
        inside: this.tickmarksInside,
        textRadius,
        rotation: this.rotation,
        maxDigits,
        color: t.color,
        radiusOffset: rOff
      })
    );
    const advices = this.advices ? this.advices.map((a) => renderAdvice(a, rOff)) : nothing;
    const insideLabels = this.tickmarksInside && this.showLabels;
    const includeNorth = !this.northArrow;
    const labelPositions = this.showLabels ? getLabelPositions({
      scale,
      inside: this.tickmarksInside,
      innerRadius: this.innerRingRadius + rOff,
      includeNorth
    }) : void 0;
    const labels = labelPositions ? renderLabels({
      scale,
      rotation: this.rotation,
      inside: this.tickmarksInside,
      innerRadius: this.innerRingRadius + rOff,
      includeNorth
    }) : nothing;
    const northArrowEl = this.northArrow ? renderNorthArrow({
      scale,
      rotation: this.rotation,
      inside: this.northArrowInside ?? this.tickmarksInside
    }) : nothing;
    const wind = this.wind != null && this.windFromDirectionDeg != null ? svg`<g transform="scale(${this.scaleWindIcon})">${renderWind({
      wind: this.wind,
      fromDirectionDeg: this.windFromDirectionDeg,
      radius: this.windSymbolRadius ?? 192,
      color: this.windColor
    })}</g>` : nothing;
    const current = this.current != null && this.currentFromDirectionDeg != null ? renderCurrent({
      current: this.current,
      fromDirectionDeg: this.currentFromDirectionDeg,
      radius: this.currentSymbolRadius ?? 192,
      color: this.currentColor
    }) : nothing;
    return html`
      <svg
        width="100%"
        height="100%"
        viewBox=${viewBox}
        style="--scale: ${scale}"
        transform="rotate(${this.rotation ?? 0})"
      >
        ${this.watchCircle()} ${this.renderBars()}
        ${this.crosshairEnabled ? this.renderCrosshair(
      OUTER_RING_RADIUS + rOff,
      insideLabels && labelPositions ? {
        positions: labelPositions,
        rotation: this.rotation,
        scale,
        innerRingRadius: this.innerRingRadius + rOff
      } : void 0
    ) : nothing}
        ${northArrowEl} ${this.renderStarboardPortIndicator()} ${current}
        ${this._renderTickFadeDefs()} ${wind}
        ${this.tickFadeAngle > 0 && this.areas.length > 0 ? svg`<g mask="url(#tickFadeMask)">${tickmarks}</g>` : tickmarks}
        ${this.areas.length > 0 ? svg`<g clip-path="url(#rot-arc-clip)">${this.renderRot()}</g>` : this.renderRot()}
        ${advices} ${angleSetpoint}
        ${this.tickFadeAngle > 0 && this.areas.length > 0 ? svg`<g mask="url(#tickFadeMask)">${labels}</g>` : labels}
        ${this.renderVesselImage()} ${this.renderNeedles()}
      </svg>
    `;
  }
  getRotColors() {
    const p = this.rotPriority ?? this.priority;
    const isEnhanced = p === Priority.enhanced;
    const isInner = this.rotPosition === RotPosition.innerCircle;
    if (isInner) {
      return {
        dotColor: isEnhanced ? "var(--instrument-enhanced-tertiary-color)" : "var(--instrument-regular-tertiary-color)",
        barBgColor: isEnhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)",
        endDotFill: "var(--border-silhouette-color)",
        endDotStroke: isEnhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)"
      };
    }
    return {
      dotColor: isEnhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)",
      barBgColor: isEnhanced ? "var(--instrument-enhanced-tertiary-color)" : "var(--instrument-regular-tertiary-color)",
      endDotFill: isEnhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--border-silhouette-color)",
      endDotStroke: isEnhanced ? "var(--instrument-frame-primary-color)" : "var(--instrument-regular-secondary-color)"
    };
  }
  renderRot() {
    if (!this.rotType) return nothing;
    const { dotColor, barBgColor, endDotFill, endDotStroke } = this.getRotColors();
    const rOff = this._rOff;
    if (this.rotType === RotType.bar) {
      const hasBar = shortestAngularDeltaDeg(this.rotStartAngle, this.rotEndAngle) >= 0.1;
      return svg`
        ${renderRotBarStatic({
        startAngle: this.rotStartAngle,
        endAngle: this.rotEndAngle,
        color: dotColor,
        barColor: barBgColor,
        position: this.rotPosition,
        endDotFill,
        endDotStroke,
        maskId: "rot-bar-mask",
        radiusOffset: rOff
      })}
        ${hasBar ? svg`<g clip-path="url(#rot-bar-mask)">
              <g id="rot-spinner">
                ${renderRotBarDots(dotColor, this.rotPosition, rOff)}
              </g>
            </g>` : nothing}
      `;
    }
    const p = this.rotPriority ?? this.priority;
    const dotsColor = p === Priority.enhanced ? "var(--instrument-enhanced-secondary-color)" : "var(--instrument-regular-secondary-color)";
    return svg`
      <g id="rot-spinner">
        ${renderRotDots(dotsColor, this.rotPosition, rOff)}
      </g>
    `;
  }
  renderSetpoint() {
    if (this.angleSetpoint === void 0) {
      return nothing;
    }
    const derived = deriveRadialSetpointConfig({
      state: this.state,
      priority: this.priority,
      atSetpoint: this.atAngleSetpoint,
      angleSetpoint: this.angleSetpoint,
      setpointAtZeroDeadband: this.angleSetpointAtZeroDeadband,
      newAngleSetpoint: this.newAngleSetpoint,
      touching: this.touching,
      setpointOverride: this.setpointOverride
    });
    const { visualState, colorMode, disabled, hasNewSetpoint } = derived;
    const outwardOffset = getSetpointOutwardOffset(visualState);
    const radius = RADIAL_SETPOINT_RADIUS + this._rOff + outwardOffset - RADIAL_SETPOINT_INWARD_ADJUST;
    const opacity = hasNewSetpoint ? 0.75 : 1;
    const originalMarker = drawSetpointMarker({
      visualState,
      colorMode,
      disabled,
      id: this._setpointId
    });
    const animate = this.animateSetpoint;
    const hasDeparting = this._departingNewAngleSetpoint !== void 0;
    const rawAngle = this.angleSetpoint + 90;
    if (!this._setpointCssAngleInit) {
      this._setpointCssAngle = rawAngle;
      this._setpointCssAngleInit = true;
    } else {
      this._setpointCssAngle = cssSafeAngle(this._setpointCssAngle, rawAngle);
    }
    const originalSetpoint = animate ? svg`
        <g style="transform: rotate(${this._setpointCssAngle}deg) translateX(${-radius}px) rotate(270deg); opacity: ${opacity}; transition: transform var(${SETPOINT_ANIMATION_CSS_VAR}, ${SETPOINT_ANIMATION_DURATION_DEFAULT}) ease-out, opacity var(${SETPOINT_ANIMATION_CSS_VAR}, ${SETPOINT_ANIMATION_DURATION_DEFAULT}) ease-out;">
          ${originalMarker}
        </g>
      ` : svg`
        <g transform="rotate(${this.angleSetpoint + 90}) translate(${-radius}, 0) rotate(270)" opacity="${opacity}">
          ${originalMarker}
        </g>
      `;
    if (hasNewSetpoint || hasDeparting) {
      const isActive = hasNewSetpoint;
      const newAngle = isActive ? this.newAngleSetpoint : this._departingNewAngleSetpoint;
      const targetOpacity = isActive ? 1 : 0;
      const focusOutwardOffset = getSetpointOutwardOffset(
        SetpointVisualState.focus
      );
      const focusRadius = RADIAL_SETPOINT_RADIUS + this._rOff + focusOutwardOffset - RADIAL_SETPOINT_INWARD_ADJUST;
      const newMarker = drawSetpointMarker({
        visualState: SetpointVisualState.focus,
        colorMode,
        disabled: false,
        // newSetpoint is never disabled
        id: this._newSetpointId
      });
      if (animate) {
        const duration = `var(${SETPOINT_ANIMATION_CSS_VAR}, ${SETPOINT_ANIMATION_DURATION_DEFAULT})`;
        return svg`
          ${originalSetpoint}
          <g style="transform: rotate(${newAngle + 90}deg) translateX(${-focusRadius}px) rotate(270deg); opacity: ${targetOpacity}; transition: opacity ${duration} ease-out;">
            ${newMarker}
          </g>
        `;
      }
      return svg`
        ${originalSetpoint}
        <g transform="rotate(${newAngle + 90}) translate(${-focusRadius}, 0) rotate(270)" opacity="${targetOpacity}">
          ${newMarker}
        </g>
      `;
    }
    return originalSetpoint;
  }
  renderVesselImage() {
    if (this.vessels.length === 0) {
      return nothing;
    }
    return this.vessels.map((v) => {
      let size;
      switch (v.size) {
        case VesselImageSize.large:
          size = 224;
          break;
        case VesselImageSize.medium:
          size = 160;
          break;
        default:
          size = 100;
      }
      const scale = size / 160;
      return svg`<g style="transform: ${v.transform} scale(${scale}) translate(-80px, -80px) ">${vesselImages[v.vesselImage]}</g>`;
    });
  }
  renderStarboardPortIndicator() {
    if (!this.starboardPortIndicator) {
      return nothing;
    }
    return [
      adviceMask(
        0,
        180,
        "var(--instrument-starboard-secondary-color)",
        "var(--instrument-starboard-secondary-color)"
      ),
      adviceMask(
        180,
        360,
        "var(--instrument-port-secondary-color)",
        "var(--instrument-port-secondary-color)"
      )
    ];
  }
};
ObcWatch.styles = unsafeCSS(compentStyle);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "state", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "priority", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "watchCircleType", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "northArrow", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "northArrowInside", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "angleSetpoint", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "newAngleSetpoint", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "atAngleSetpoint", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "angleSetpointAtZeroDeadband", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "setpointOverride", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "touching", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "animateSetpoint", 2);
__decorateClass([
  state()
], ObcWatch.prototype, "_departingNewAngleSetpoint", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "padding", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "areas", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "barAreas", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "needles", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "tickmarks", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "tickmarksInside", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "tickmarkStyle", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "advices", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "crosshairEnabled", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "showLabels", 2);
__decorateClass([
  property({ type: Array, attribute: false })
], ObcWatch.prototype, "vessels", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "wind", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "windFromDirectionDeg", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "windSymbolRadius", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "windColor", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "current", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "currentFromDirectionDeg", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "currentSymbolRadius", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "currentColor", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "starboardPortIndicator", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "clipTop", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "clipBottom", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "scaleWindIcon", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "rotation", 2);
__decorateClass([
  property({ type: Boolean })
], ObcWatch.prototype, "zoomToFitArc", 2);
__decorateClass([
  property({ attribute: false })
], ObcWatch.prototype, "arcFrame", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "tickFadeAngle", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "rotType", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "rotPosition", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "rotStartAngle", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "rotEndAngle", 2);
__decorateClass([
  property({ type: String })
], ObcWatch.prototype, "rotPriority", 2);
__decorateClass([
  property({ type: Number })
], ObcWatch.prototype, "rotationsPerMinute", 1);
ObcWatch = __decorateClass([
  customElement("obc-watch")
], ObcWatch);
export {
  OUTER_RING_RADIUS,
  ObcWatch,
  RotPosition,
  RotType,
  TickmarkStyle,
  VesselImage,
  VesselImageSize,
  WatchCircleType,
  innerRingRadiusFor
};
//# sourceMappingURL=watch.js.map
