<script>
  import { onMount, onDestroy } from 'svelte';
  import { api } from './lib/api.js';
  import { wsService, connected, systemStatus } from './lib/websocket.js';

  let status = null;
  let isConnected = false;

  const unsubStatus = systemStatus.subscribe(v => { status = v; });
  const unsubConn = connected.subscribe(v => { isConnected = v; });

  // Rotator state
  let heading = null;
  let localTargetHeading = null;

  $: rotator = status?.rotator_genius;
  $: ultrabeam = status?.ultrabeam;
  $: ultrabeamDirection = ultrabeam?.direction ?? 0;

  $: if (rotator?.heading !== undefined && rotator?.heading !== null) {
    const newHeading = rotator.heading;
    if (heading === null) {
      heading = newHeading;
    } else if (newHeading === 0 && heading > 10 && heading < 350) {
      // ignore glitch
    } else {
      heading = newHeading;
    }
  }

  $: displayHeading = heading !== null ? heading : 0;
  $: connected2 = rotator?.connected || false;

  $: statusTargetHeading = rotator?.target_heading ?? null;

  $: isMovingFromStatus = statusTargetHeading !== null &&
    heading !== null &&
    (() => {
      const diff = Math.abs(statusTargetHeading - heading);
      return Math.min(diff, 360 - diff) > 2;
    })();

  $: activeTargetHeading = localTargetHeading ?? (isMovingFromStatus ? statusTargetHeading : null);

  $: hasTarget = activeTargetHeading !== null && heading !== null && (() => {
    const diff = Math.abs(activeTargetHeading - heading);
    return Math.min(diff, 360 - diff) > 2;
  })();

  $: if (localTargetHeading !== null && heading !== null) {
    const diff = Math.abs(heading - localTargetHeading);
    if (Math.min(diff, 360 - diff) < 3) {
      localTargetHeading = null;
    }
  }

  // Ultrabeam direction state (local copy for immediate UI feedback)
  let targetDirection = 0;
  $: targetDirection = ultrabeamDirection;

  onMount(() => {
    wsService.connect();
  });

  onDestroy(() => {
    wsService.disconnect();
    unsubStatus();
    unsubConn();
  });

  async function rotateCW() {
    try { await api.rotator.rotateCW(); } catch (e) {}
  }
  async function rotateCCW() {
    try { await api.rotator.rotateCCW(); } catch (e) {}
  }
  async function stop() {
    localTargetHeading = null;
    try { await api.rotator.stop(); } catch (e) {}
  }

  async function handleCompassClick(event) {
    const svg = event.currentTarget;
    const rect = svg.getBoundingClientRect();
    const x = event.clientX - rect.left - rect.width / 2;
    const y = event.clientY - rect.top - rect.height / 2;
    let angle = Math.atan2(x, -y) * (180 / Math.PI);
    if (angle < 0) angle += 360;
    const adjusted = (Math.round(angle / 5) * 5 + 360) % 360;
    try {
      await api.rotator.setHeading(adjusted);
      localTargetHeading = adjusted;
    } catch (e) {}
  }

  async function setDirection(dir) {
    targetDirection = dir;
    try {
      const freq = ultrabeam?.frequency || 0;
      if (freq > 0) {
        await api.ultrabeam.setFrequency(freq, dir);
      }
      await api.ultrabeam.setDirection(dir);
    } catch (e) {}
  }
</script>

<div class="popup-root">
  <!-- Header -->
  <div class="header">
    <div class="header-left">
      <span class="status-dot" class:disconnected={!connected2}></span>
      <span class="title">Rotator Control</span>
    </div>
    <div class="heading-value">
      {displayHeading}°
      {#if hasTarget && activeTargetHeading !== null}
        <span class="target-indicator">→ {activeTargetHeading}°</span>
      {/if}
    </div>
    <div class="controls-compact">
      <button class="btn-mini ccw" on:click={rotateCCW} title="Rotate CCW">↺</button>
      <button class="btn-mini stop-btn" on:click={stop} title="Stop">■</button>
      <button class="btn-mini cw" on:click={rotateCW} title="Rotate CW">↻</button>
    </div>
  </div>

  <!-- Compass Map -->
  <div class="map-container">
    <svg viewBox="0 0 300 300" class="map-svg"
         on:click={handleCompassClick}
         on:keydown={(e) => e.key === 'Enter' && handleCompassClick(e)}
         role="button"
         tabindex="0"
         aria-label="Click to rotate antenna">
      <defs>
        <radialGradient id="beamGrad">
          <stop offset="0%" style="stop-color:rgba(79,195,247,0.7);stop-opacity:1" />
          <stop offset="100%" style="stop-color:rgba(79,195,247,0);stop-opacity:0" />
        </radialGradient>
      </defs>

      <circle cx="150" cy="150" r="140" fill="rgba(30,64,175,0.15)" stroke="rgba(79,195,247,0.4)" stroke-width="2"/>
      <circle cx="150" cy="150" r="105" fill="none" stroke="rgba(79,195,247,0.2)" stroke-width="1" stroke-dasharray="3,3"/>
      <circle cx="150" cy="150" r="70"  fill="none" stroke="rgba(79,195,247,0.2)" stroke-width="1" stroke-dasharray="3,3"/>
      <circle cx="150" cy="150" r="35"  fill="none" stroke="rgba(79,195,247,0.2)" stroke-width="1" stroke-dasharray="3,3"/>

      <g transform="translate(150,150)">
        <!-- Physical antenna indicator (180° / Bi-Dir) -->
        {#if ultrabeamDirection === 1 || ultrabeamDirection === 2}
          <g transform="rotate({displayHeading})">
            <line x1="0" y1="0" x2="0" y2="-125"
                  stroke="rgba(255,255,255,0.3)" stroke-width="2" stroke-dasharray="5,5" opacity="0.6"/>
            <g transform="translate(0,-125)">
              <polygon points="0,-8 -5,5 5,5"
                       fill="rgba(255,255,255,0.4)" stroke="rgba(255,255,255,0.5)" stroke-width="1"/>
            </g>
          </g>
        {/if}

        <g transform="rotate({displayHeading})">
          {#if ultrabeamDirection === 0}
            <path d="M 0,0 L {-Math.sin(15*Math.PI/180)*130},{-Math.cos(15*Math.PI/180)*130}
                     A 130,130 0 0,1 {Math.sin(15*Math.PI/180)*130},{-Math.cos(15*Math.PI/180)*130} Z"
                  fill="url(#beamGrad)" opacity="0.85"/>
            <line x1="0" y1="0" x2={-Math.sin(15*Math.PI/180)*130} y2={-Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.9"/>
            <line x1="0" y1="0" x2={Math.sin(15*Math.PI/180)*130} y2={-Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.9"/>
            <g transform="translate(0,-110)">
              <polygon points="0,-20 -8,5 0,0 8,5" fill="#4fc3f7" stroke="#0288d1" stroke-width="2"
                       style="filter:drop-shadow(0 0 10px rgba(79,195,247,1))"/>
            </g>
          {/if}

          {#if ultrabeamDirection === 1}
            <path d="M 0,0 L {-Math.sin(15*Math.PI/180)*130},{Math.cos(15*Math.PI/180)*130}
                     A 130,130 0 0,0 {Math.sin(15*Math.PI/180)*130},{Math.cos(15*Math.PI/180)*130} Z"
                  fill="url(#beamGrad)" opacity="0.85"/>
            <line x1="0" y1="0" x2={-Math.sin(15*Math.PI/180)*130} y2={Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.9"/>
            <line x1="0" y1="0" x2={Math.sin(15*Math.PI/180)*130} y2={Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.9"/>
            <g transform="translate(0,110)">
              <polygon points="0,20 -8,-5 0,0 8,-5" fill="#4fc3f7" stroke="#0288d1" stroke-width="2"
                       style="filter:drop-shadow(0 0 10px rgba(79,195,247,1))"/>
            </g>
          {/if}

          {#if ultrabeamDirection === 2}
            <path d="M 0,0 L {-Math.sin(15*Math.PI/180)*130},{-Math.cos(15*Math.PI/180)*130}
                     A 130,130 0 0,1 {Math.sin(15*Math.PI/180)*130},{-Math.cos(15*Math.PI/180)*130} Z"
                  fill="url(#beamGrad)" opacity="0.7"/>
            <path d="M 0,0 L {-Math.sin(15*Math.PI/180)*130},{Math.cos(15*Math.PI/180)*130}
                     A 130,130 0 0,0 {Math.sin(15*Math.PI/180)*130},{Math.cos(15*Math.PI/180)*130} Z"
                  fill="url(#beamGrad)" opacity="0.7"/>
            <line x1="0" y1="0" x2={-Math.sin(15*Math.PI/180)*130} y2={-Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.8"/>
            <line x1="0" y1="0" x2={Math.sin(15*Math.PI/180)*130} y2={-Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.8"/>
            <line x1="0" y1="0" x2={-Math.sin(15*Math.PI/180)*130} y2={Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.8"/>
            <line x1="0" y1="0" x2={Math.sin(15*Math.PI/180)*130} y2={Math.cos(15*Math.PI/180)*130}
                  stroke="#4fc3f7" stroke-width="2" opacity="0.8"/>
            <g transform="translate(0,-110)">
              <polygon points="0,-20 -8,5 0,0 8,5" fill="#4fc3f7" stroke="#0288d1" stroke-width="2"
                       style="filter:drop-shadow(0 0 10px rgba(79,195,247,1))"/>
            </g>
            <g transform="translate(0,110)">
              <polygon points="0,20 -8,-5 0,0 8,-5" fill="#4fc3f7" stroke="#0288d1" stroke-width="2"
                       style="filter:drop-shadow(0 0 10px rgba(79,195,247,1))"/>
            </g>
          {/if}
        </g>

        <!-- Target arrow -->
        {#if hasTarget && activeTargetHeading !== null}
          <g transform="rotate({activeTargetHeading})">
            <line x1="0" y1="0" x2="0" y2="-135"
                  stroke="#ffc107" stroke-width="3" stroke-dasharray="8,4" opacity="0.9"/>
            <g transform="translate(0,-135)">
              <polygon points="0,-12 -8,6 0,2 8,6"
                       fill="#ffc107" stroke="#ff9800" stroke-width="1.5"
                       style="filter:drop-shadow(0 0 10px rgba(255,193,7,0.8))">
                <animate attributeName="opacity" values="0.8;1;0.8" dur="1s" repeatCount="indefinite"/>
              </polygon>
            </g>
          </g>
        {/if}

        <!-- QTH dot -->
        <circle cx="0" cy="0" r="5" fill="#f44336" stroke="#fff" stroke-width="2">
          <animate attributeName="r" values="5;7;5" dur="2s" repeatCount="indefinite"/>
        </circle>
        <circle cx="0" cy="0" r="10" fill="none" stroke="#f44336" stroke-width="1.5" opacity="0.5">
          <animate attributeName="r" values="10;16;10" dur="2s" repeatCount="indefinite"/>
          <animate attributeName="opacity" values="0.5;0;0.5" dur="2s" repeatCount="indefinite"/>
        </circle>
      </g>

      <!-- Cardinals -->
      <text x="150" y="20"  text-anchor="middle" class="cardinal">N</text>
      <text x="280" y="155" text-anchor="middle" class="cardinal">E</text>
      <text x="150" y="285" text-anchor="middle" class="cardinal">S</text>
      <text x="20"  y="155" text-anchor="middle" class="cardinal">W</text>

      {#each [45,135,225,315] as angle}
        {@const x = 150 + 125 * Math.sin(angle * Math.PI / 180)}
        {@const y = 150 - 125 * Math.cos(angle * Math.PI / 180)}
        <text {x} {y} text-anchor="middle" dominant-baseline="middle" class="degree-label">{angle}°</text>
      {/each}
    </svg>
  </div>

  <!-- Ultrabeam Direction Buttons -->
  <div class="dir-row">
    <button class="dir-btn" class:active={targetDirection === 0} on:click={() => setDirection(0)}>Normal</button>
    <button class="dir-btn" class:active={targetDirection === 1} on:click={() => setDirection(1)}>180°</button>
    <button class="dir-btn" class:active={targetDirection === 2} on:click={() => setDirection(2)}>Bi-Dir</button>
  </div>
</div>

<style>
  :global(html, body) {
    background: #0f1923;
    color: #e0e0e0;
    font-family: 'Roboto', sans-serif;
    margin: 0;
    padding: 0;
    overflow: hidden;
    height: 100%;
  }

  .popup-root {
    display: flex;
    flex-direction: column;
    height: 100vh;
    background: linear-gradient(135deg, #1a2332 0%, #0f1923 100%);
    user-select: none;
  }

  .header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    background: rgba(79,195,247,0.05);
    border-bottom: 1px solid #2d3748;
    gap: 8px;
    flex-shrink: 0;
  }

  .header-left {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }

  .title {
    font-size: 12px;
    font-weight: 600;
    color: #4fc3f7;
    letter-spacing: 0.5px;
    white-space: nowrap;
  }

  .status-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #4caf50;
    box-shadow: 0 0 6px #4caf50;
    flex-shrink: 0;
  }

  .status-dot.disconnected {
    background: #f44336;
    box-shadow: 0 0 6px #f44336;
  }

  .heading-value {
    font-size: 28px;
    font-weight: 200;
    color: #4fc3f7;
    text-shadow: 0 0 15px rgba(79,195,247,0.5);
    white-space: nowrap;
  }

  .target-indicator {
    font-size: 16px;
    font-weight: 400;
    color: #ffc107;
    margin-left: 8px;
    text-shadow: 0 0 10px rgba(255,193,7,0.6);
    animation: pulse 1s ease-in-out infinite;
  }

  @keyframes pulse {
    0%, 100% { opacity: 0.8; }
    50% { opacity: 1; }
  }

  .controls-compact {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
  }

  .btn-mini {
    width: 30px;
    height: 30px;
    border: 2px solid rgba(79,195,247,0.3);
    border-radius: 5px;
    font-size: 17px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgba(255,255,255,0.7);
    background: rgba(79,195,247,0.08);
    transition: all 0.2s;
  }

  .btn-mini:hover {
    border-color: rgba(79,195,247,0.6);
    color: rgba(255,255,255,0.9);
    background: rgba(79,195,247,0.15);
  }

  .btn-mini.stop-btn:hover {
    border-color: #f44336;
    color: #f44336;
    background: rgba(244,67,54,0.15);
  }

  .map-container {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 6px;
    background: rgba(10,22,40,0.6);
    min-height: 0;
  }

  .map-svg {
    width: 100%;
    height: 100%;
    max-width: 360px;
    max-height: 360px;
    cursor: crosshair;
    outline: none;
  }

  .map-svg:hover {
    filter: brightness(1.1);
  }

  .cardinal {
    fill: #4fc3f7;
    font-size: 16px;
    font-weight: 700;
  }

  .degree-label {
    fill: rgba(79,195,247,0.7);
    font-size: 12px;
    font-weight: 600;
  }

  .dir-row {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
    padding: 8px;
    border-top: 1px solid #2d3748;
    flex-shrink: 0;
  }

  .dir-btn {
    padding: 8px 0;
    border: 2px solid rgba(79,195,247,0.3);
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    cursor: pointer;
    color: rgba(255,255,255,0.7);
    background: rgba(79,195,247,0.08);
    letter-spacing: 0.5px;
    transition: all 0.2s;
  }

  .dir-btn:hover {
    border-color: rgba(79,195,247,0.6);
    color: rgba(255,255,255,0.9);
    background: rgba(79,195,247,0.15);
  }

  .dir-btn.active {
    border-color: #4fc3f7;
    color: #4fc3f7;
    background: rgba(79,195,247,0.2);
    box-shadow: 0 0 15px rgba(79,195,247,0.3);
    font-weight: 700;
  }
</style>
