'use strict';

(() => {
  const VERSION = 1;
  let sequence = 0;

  function nextId(prefix) {
    sequence += 1;
    return `${prefix}-${sequence}`;
  }

  function clampLevel(level) {
    return Math.max(1, Math.min(5, Number(level) || 1));
  }

  function textureDefs(id, width, height) {
    return `<defs>
      <pattern id="${id}-stone" patternUnits="userSpaceOnUse" width="96" height="96">
        <image href="../assets/castle/stone_wall_texture.jpg" x="0" y="0" width="96" height="96" preserveAspectRatio="xMidYMid slice"/>
      </pattern>
      <linearGradient id="${id}-top" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="#ddd6be"/>
        <stop offset="1" stop-color="#918b7b"/>
      </linearGradient>
      <linearGradient id="${id}-shade" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0" stop-color="#ffffff" stop-opacity=".18"/>
        <stop offset="1" stop-color="#161a17" stop-opacity=".42"/>
      </linearGradient>
      <filter id="${id}-shadow" x="-30%" y="-30%" width="160%" height="180%">
        <feDropShadow dx="0" dy="6" stdDeviation="4" flood-color="#101711" flood-opacity=".58"/>
      </filter>
      <clipPath id="${id}-face"><path d="M10 29 L76 56 L141 34 L141 82 L76 108 L10 78 Z"/></clipPath>
    </defs>`;
  }

  function block(x, y, scale = 1, id = 'b') {
    const w = 20 * scale;
    const h = 11 * scale;
    const d = 15 * scale;
    return `<g transform="translate(${x} ${y})">
      <polygon points="0,${h} ${w},0 ${w * 2},${h} ${w},${h * 2}" fill="#d8d1b9" stroke="#5d5c55" stroke-width="1"/>
      <polygon points="0,${h} ${w},${h * 2} ${w},${h * 2 + d} 0,${h + d}" fill="#858277" stroke="#55544e" stroke-width="1"/>
      <polygon points="${w * 2},${h} ${w},${h * 2} ${w},${h * 2 + d} ${w * 2},${h + d}" fill="#a9a596" stroke="#5b5a53" stroke-width="1"/>
    </g>`;
  }

  function wallArt(level, orientation) {
    const tier = clampLevel(level);
    const id = nextId('wall');
    const mirror = orientation.startsWith('y') ? 'translate(150 0) scale(-1 1)' : '';
    const heightLift = (tier - 1) * 2;
    const battlements = [8, 35, 62, 89, 116].map((x, index) => block(x, 8 - heightLift + (index % 2), tier >= 4 ? 1.05 : 1, id)).join('');
    const buttresses = tier >= 3
      ? `<path d="M25 57 L37 62 L37 91 L25 86 Z M113 48 L125 44 L125 72 L113 77 Z" fill="#74736b" stroke="#4f504a" stroke-width="1.4"/>`
      : '';
    const gold = tier >= 5 ? `<path d="M74 63 l8 4 v17 l-8 4 l-8-4 V67z" fill="#a97a22" stroke="#e5c166" stroke-width="1.5"/><path d="M70 72h8M74 68v13" stroke="#f4d582" stroke-width="1.4"/>` : '';
    return `<svg viewBox="0 0 150 112" aria-hidden="true">
      ${textureDefs(id, 150, 112)}
      <g transform="${mirror}" filter="url(#${id}-shadow)">
        <ellipse cx="76" cy="103" rx="64" ry="8" fill="#172018" opacity=".34"/>
        <path d="M10 29 L76 56 L141 34 L141 82 L76 108 L10 78 Z" fill="url(#${id}-stone)" stroke="#3f423d" stroke-width="2"/>
        <path d="M10 29 L76 7 L141 34 L76 56 Z" fill="url(#${id}-top)" stroke="#595951" stroke-width="2"/>
        <path d="M10 29 L76 56 L76 108 L10 78 Z" fill="#4a4d48" opacity=".3"/>
        <path d="M76 56 L141 34 L141 82 L76 108 Z" fill="url(#${id}-shade)" opacity=".62"/>
        <g clip-path="url(#${id}-face)" opacity=".55" stroke="#4b4c46" stroke-width="1">
          <path d="M2 51 L150 51 M2 70 L150 70 M2 90 L150 90"/>
          <path d="M25 45V62 M50 54V76 M100 48V65 M124 41V59 M38 70V88 M88 67V87 M116 76V94"/>
        </g>
        ${buttresses}
        <path d="M73 70 q3-8 7 0 v17 h-7z" fill="#202724" stroke="#aaa897" stroke-width="1.5"/>
        ${battlements}
        <path d="M14 31 L76 10 L137 35" fill="none" stroke="#f4edd6" stroke-opacity=".55" stroke-width="2"/>
        ${gold}
      </g>
    </svg>`;
  }

  function towerArt(level) {
    const tier = clampLevel(level);
    const id = nextId('tower');
    const roof = tier >= 3
      ? `<g>
          <polygon points="85,10 36,60 85,79 134,60" fill="#7b2924" stroke="#3b201b" stroke-width="2"/>
          <polygon points="85,10 85,79 36,60" fill="#54231f" opacity=".72"/>
          <path d="M85 10V-2" stroke="#3b2a19" stroke-width="3"/><path d="M87 0 l31 10 -25 15 -6-4z" fill="#a5242c" stroke="#61141a" stroke-width="1.5"/>
        </g>`
      : '';
    const battlements = tier < 3
      ? [28, 57, 86, 115].map(x => block(x, 31, 0.9, id)).join('')
      : '';
    return `<svg viewBox="0 0 170 220" aria-hidden="true">
      ${textureDefs(id, 170, 220)}
      <g filter="url(#${id}-shadow)">
        <ellipse cx="85" cy="204" rx="62" ry="12" fill="#172018" opacity=".4"/>
        <path d="M30 68 L85 46 L140 68 L140 174 L85 205 L30 174 Z" fill="url(#${id}-stone)" stroke="#3f423d" stroke-width="3"/>
        <path d="M30 68 L85 46 L140 68 L85 92 Z" fill="url(#${id}-top)" stroke="#55564f" stroke-width="2"/>
        <path d="M30 68 L85 92 L85 205 L30 174 Z" fill="#484b46" opacity=".34"/>
        <path d="M85 92 L140 68 L140 174 L85 205 Z" fill="url(#${id}-shade)" opacity=".6"/>
        <path d="M42 101H128 M42 127H128 M42 153H128" stroke="#4e504a" stroke-width="1.5" opacity=".65"/>
        <path d="M58 82V108 M112 79V108 M49 127V151 M84 118V148 M119 118V149 M61 153V178 M110 151V179" stroke="#4b4d48" stroke-width="1" opacity=".55"/>
        <path d="M76 130 q9-19 18 0 v43 H76z" fill="#232925" stroke="#b9b4a1" stroke-width="2"/>
        <path d="M80 137h10M80 145h10M80 153h10" stroke="#111612" stroke-width="2"/>
        <path d="M50 115 q4-11 8 0 v22 h-8z M112 109 q4-11 8 0 v22 h-8z" fill="#1f2624" stroke="#aaa797" stroke-width="1.5"/>
        ${battlements}${roof}
        ${tier >= 4 ? '<path d="M42 161 L55 155 L55 187 L42 181 Z M115 151 L128 145 L128 177 L115 183 Z" fill="#6d6e67" stroke="#4c4d48" stroke-width="1.5"/>' : ''}
        ${tier >= 5 ? '<circle cx="85" cy="107" r="12" fill="#a77a23" stroke="#ead085" stroke-width="2"/><path d="M78 107h14M85 100v14" stroke="#f4ddb0" stroke-width="2"/>' : ''}
      </g>
    </svg>`;
  }

  function gateArt(level) {
    const tier = clampLevel(level);
    const id = nextId('gate');
    const roof = tier >= 3
      ? `<polygon points="110,7 76,43 110,58 144,43" fill="#842d27" stroke="#43211d" stroke-width="2"/>
         <polygon points="110,7 110,58 76,43" fill="#57231f" opacity=".78"/>
         <path d="M110 7V-2" stroke="#342719" stroke-width="3"/><path d="M112 0l30 10-24 13-6-4z" fill="#a8242c"/>`
      : '';
    const sideBlocks = [18, 48, 146, 176].map((x, index) => block(x, 36 + (index % 2 ? 2 : 0), 0.95, id)).join('');
    return `<svg viewBox="0 0 220 182" aria-hidden="true">
      ${textureDefs(id, 220, 182)}
      <g filter="url(#${id}-shadow)">
        <ellipse cx="110" cy="171" rx="94" ry="11" fill="#172018" opacity=".42"/>
        <path d="M14 53 L67 35 L110 51 L153 35 L206 53 L206 140 L110 177 L14 140 Z" fill="url(#${id}-stone)" stroke="#3f423d" stroke-width="3"/>
        <path d="M14 53 L67 35 L110 51 L153 35 L206 53 L110 88 Z" fill="url(#${id}-top)" stroke="#55564f" stroke-width="2"/>
        <path d="M14 53 L110 88 L110 177 L14 140 Z" fill="#444843" opacity=".32"/>
        <path d="M110 88 L206 53 L206 140 L110 177 Z" fill="url(#${id}-shade)" opacity=".52"/>
        <path d="M72 103 Q110 61 148 103 V163 L72 163 Z" fill="#252a27" stroke="#c0baa5" stroke-width="4"/>
        <path d="M80 108 Q110 74 140 108 V161 H80 Z" fill="#5b351d" stroke="#2f2117" stroke-width="3"/>
        <path d="M110 82V161 M86 107V157 M98 95V160 M122 95V160 M134 107V157" stroke="#2d1e14" stroke-width="3" opacity=".9"/>
        <path d="M81 118H139 M81 133H139 M81 148H139" stroke="#8b6842" stroke-width="2"/>
        <path d="M44 91 q5-13 10 0 v24 H44z M166 91 q5-13 10 0 v24 h-10z" fill="#202724" stroke="#aaa797" stroke-width="1.5"/>
        <path d="M22 87H198 M22 113H198 M22 137H198" stroke="#4c4e48" stroke-width="1.3" opacity=".55"/>
        ${sideBlocks}${roof}
        <path d="M57 75v48 l-18-7V68z" fill="#9d2029" stroke="#5b151b" stroke-width="2"/><path d="M163 75v48 l18-7V68z" fill="#9d2029" stroke="#5b151b" stroke-width="2"/>
        ${tier >= 4 ? '<path d="M24 128 L40 121 L40 151 L24 146 Z M180 120 L196 114 L196 143 L180 149 Z" fill="#70716a" stroke="#4a4b46" stroke-width="1.5"/>' : ''}
        ${tier >= 5 ? '<circle cx="110" cy="69" r="14" fill="#a77a23" stroke="#ead085" stroke-width="2"/><path d="M102 69h16M110 61v16" stroke="#f5ddb0" stroke-width="2"/>' : ''}
      </g>
    </svg>`;
  }

  function courtyard(bounds, project) {
    const min = bounds.min - 0.58;
    const max = bounds.max + 0.58;
    const top = project(min, min);
    const right = project(max, min);
    const bottom = project(max, max);
    const left = project(min, max);
    const width = Math.max(1, right.x - left.x);
    const height = Math.max(1, bottom.y - top.y);
    return `<span class="castle-courtyard-ground" style="left:${left.x}px;top:${top.y}px;width:${width}px;height:${height}px;z-index:72">
      <span class="castle-courtyard-inner"></span>
      <span class="castle-courtyard-detail detail-a"></span>
      <span class="castle-courtyard-detail detail-b"></span>
      <span class="castle-courtyard-detail detail-c"></span>
    </span>`;
  }

  globalThis.ReinosFortificationVisuals = Object.freeze({
    VERSION,
    wallArt,
    towerArt,
    gateArt,
    courtyard,
    metrics: Object.freeze({ wall: { width: 108, height: 90 }, tower: { width: 170, height: 220 }, gate: { width: 220, height: 182 } })
  });
})();
