'use strict';

(() => {
  const base = globalThis.ReinosFortificationVisuals || {};
  let sequence = 0;

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

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

  function defs(id) {
    return `<defs>
      <linearGradient id="${id}-stone-front" x1="0" y1="0" x2="0.92" y2="1">
        <stop offset="0" stop-color="#767d80"/>
        <stop offset=".34" stop-color="#4d565a"/>
        <stop offset=".72" stop-color="#343c40"/>
        <stop offset="1" stop-color="#22292d"/>
      </linearGradient>
      <linearGradient id="${id}-stone-side" x1="0" y1="0" x2="1" y2=".8">
        <stop offset="0" stop-color="#3f484c"/>
        <stop offset="1" stop-color="#1f262a"/>
      </linearGradient>
      <linearGradient id="${id}-stone-top" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="#b5b8b4"/>
        <stop offset=".48" stop-color="#7b8282"/>
        <stop offset="1" stop-color="#50585b"/>
      </linearGradient>
      <linearGradient id="${id}-parapet" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="#949b9b"/>
        <stop offset="1" stop-color="#454e52"/>
      </linearGradient>
      <linearGradient id="${id}-red" x1="0" y1="0" x2="1" y2="0">
        <stop offset="0" stop-color="#6e1016"/>
        <stop offset=".45" stop-color="#c72530"/>
        <stop offset="1" stop-color="#7a1219"/>
      </linearGradient>
      <linearGradient id="${id}-wood" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0" stop-color="#815338"/>
        <stop offset=".55" stop-color="#4d2f21"/>
        <stop offset="1" stop-color="#291b15"/>
      </linearGradient>
      <linearGradient id="${id}-iron" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0" stop-color="#a9b0ae"/>
        <stop offset=".45" stop-color="#5c6668"/>
        <stop offset="1" stop-color="#222a2d"/>
      </linearGradient>
      <linearGradient id="${id}-water" x1="0" y1="0" x2="0" y2="1">
        <stop offset="0" stop-color="#88d3dc" stop-opacity=".9"/>
        <stop offset="1" stop-color="#28778b" stop-opacity=".96"/>
      </linearGradient>
      <radialGradient id="${id}-fire" cx="50%" cy="42%" r="60%">
        <stop offset="0" stop-color="#fff8bb"/>
        <stop offset=".36" stop-color="#ffc04a"/>
        <stop offset=".76" stop-color="#ef5a22"/>
        <stop offset="1" stop-color="#8d1717" stop-opacity=".05"/>
      </radialGradient>
      <pattern id="${id}-masonry" width="32" height="18" patternUnits="userSpaceOnUse">
        <rect width="32" height="18" fill="transparent"/>
        <path d="M0 1H32 M0 17H32 M16 1V9 M0 9H32 M5 9V17 M25 9V17" fill="none" stroke="#171e21" stroke-width="1.15" stroke-opacity=".52"/>
        <path d="M1 2H15 M17 2H31 M1 10H4 M6 10H24 M26 10H31" fill="none" stroke="#aab0af" stroke-width=".7" stroke-opacity=".18"/>
      </pattern>
      <filter id="${id}-shadow" x="-40%" y="-40%" width="190%" height="210%">
        <feDropShadow dx="0" dy="6" stdDeviation="4.5" flood-color="#0a1012" flood-opacity=".68"/>
      </filter>
      <filter id="${id}-glow" x="-150%" y="-150%" width="400%" height="400%">
        <feGaussianBlur stdDeviation="3"/>
      </filter>
      <filter id="${id}-stone-noise" x="-10%" y="-10%" width="120%" height="120%">
        <feTurbulence type="fractalNoise" baseFrequency=".74" numOctaves="2" seed="11" result="noise"/>
        <feColorMatrix in="noise" type="saturate" values="0" result="gray"/>
        <feComponentTransfer in="gray" result="faded">
          <feFuncA type="table" tableValues="0 .1"/>
        </feComponentTransfer>
        <feBlend in="SourceGraphic" in2="faded" mode="overlay"/>
      </filter>
    </defs>`;
  }

  function merlon(x, y, scale = 1) {
    const w = 10 * scale;
    const h = 5 * scale;
    const d = 12 * scale;
    return `<g transform="translate(${x} ${y})">
      <polygon points="0,${h} ${w},0 ${w * 2},${h} ${w},${h * 2}" fill="#a0a6a5" stroke="#262d30" stroke-width="1.2"/>
      <polygon points="0,${h} ${w},${h * 2} ${w},${h * 2 + d} 0,${h + d}" fill="#4a5356" stroke="#232a2d" stroke-width="1.1"/>
      <polygon points="${w * 2},${h} ${w},${h * 2} ${w},${h * 2 + d} ${w * 2},${h + d}" fill="#626b6d" stroke="#252d30" stroke-width="1.1"/>
      <path d="M2 ${h + 2} L${w} ${h * 2 - 1} L${w * 2 - 2} ${h + 2}" fill="none" stroke="#d9dcda" stroke-opacity=".24"/>
    </g>`;
  }

  function slit(x, y, scale = 1) {
    return `<g transform="translate(${x} ${y}) scale(${scale})">
      <path d="M0 9 Q5-2 10 9 V30 H0 Z" fill="#111719" stroke="#798184" stroke-width="1.4"/>
      <path d="M3 10 Q5 5 7 10 V27 H3 Z" fill="#060a0b"/>
    </g>`;
  }

  function torch(x, y, id, flip = false) {
    return `<g transform="translate(${x} ${y}) ${flip ? 'scale(-1 1)' : ''}">
      <ellipse class="rf-citadel-glow" cx="0" cy="0" rx="11" ry="11" fill="url(#${id}-fire)" opacity=".38" filter="url(#${id}-glow)"/>
      <path d="M0 5 L6 11 L4 22" fill="none" stroke="#382115" stroke-width="2.6" stroke-linecap="round"/>
      <path class="rf-citadel-flame" d="M0 6 C-7 1,-4-7,1-13 C8-6,7 1,0 6 Z" fill="url(#${id}-fire)" stroke="#8e2619" stroke-width=".8"/>
    </g>`;
  }

  function banner(x, y, id, direction = 1, royal = false, size = 1) {
    const body = direction > 0
      ? 'M3 9 C18 13 33 8 47 14 L41 34 L48 56 C32 51 18 59 3 54 Z'
      : 'M-3 9 C-18 13 -33 8 -47 14 L-41 34 L-48 56 C-32 51 -18 59 -3 54 Z';
    return `<g transform="translate(${x} ${y}) scale(${size})">
      <path d="M0 0V74" stroke="#d9ddda" stroke-width="2.8"/>
      <circle cx="0" cy="0" r="3.5" fill="#edf0ed" stroke="#50585a"/>
      <path class="rf-citadel-banner" d="${body}" fill="url(#${id}-red)" stroke="#571018" stroke-width="1.5"/>
      ${royal ? `<g transform="translate(${direction > 0 ? 23 : -23} 30)"><path d="M0-9 8-5 7 6 0 12 -7 6 -8-5Z" fill="#d2a33e" stroke="#f5d47a" stroke-width="1"/><path d="M-4 0H4M0-4V5" stroke="#fff0b6" stroke-width="1.1"/></g>` : ''}
    </g>`;
  }

  function crest(x, y, royal = false) {
    return `<g transform="translate(${x} ${y})">
      <path d="M0-14 L12-8 L10 8 L0 18 L-10 8 L-12-8 Z" fill="${royal ? '#b78b2f' : '#8f6725'}" stroke="${royal ? '#f2d783' : '#c89c4a'}" stroke-width="1.8"/>
      <path d="M-5 0H5M0-6V7" stroke="#fff0bc" stroke-width="1.7"/>
    </g>`;
  }

  function wallArt(level, orientation = '') {
    const tier = clampLevel(level);
    const id = nextId('wall');
    const mirror = orientation.startsWith('y');
    const royal = tier >= 5;
    const rear = [3, 27, 51, 75, 99, 123, 147, 171].map((x, i) => merlon(x, 27 + (i % 2) * .5, .95)).join('');
    const front = [14, 38, 62, 86, 110, 134, 158].map((x, i) => merlon(x, 48 + (i % 2) * .5, .85)).join('');
    const ornaments = tier >= 3
      ? `${banner(31, 40, id, 1, royal, .46)}${banner(169, 37, id, -1, royal, .46)}`
      : '';
    const fires = tier >= 2 ? `${torch(38, 84, id)}${torch(160, 79, id, true)}` : '';
    const moat = tier >= 4
      ? `<path d="M7 111 L99 141 L191 111 L191 121 L99 153 L7 121 Z" fill="url(#${id}-water)" opacity=".9"/><path d="M14 114 L99 142 L184 114" fill="none" stroke="#c4eff1" stroke-width="1.6" stroke-opacity=".62"/>`
      : '';

    return `<svg viewBox="0 0 198 156" aria-hidden="true">
      ${defs(id)}
      <g transform="${mirror ? 'translate(198 0) scale(-1 1)' : ''}" filter="url(#${id}-shadow)">
        ${moat}
        <ellipse cx="99" cy="132" rx="87" ry="9" fill="#0b1012" opacity=".34"/>
        <path d="M8 48 L99 77 L190 48 L190 108 L99 139 L8 108 Z" fill="url(#${id}-stone-front)" stroke="#171e21" stroke-width="2.4" filter="url(#${id}-stone-noise)"/>
        <path d="M8 48 L99 20 L190 48 L99 77 Z" fill="url(#${id}-stone-top)" stroke="#2a3235" stroke-width="2"/>
        <path d="M8 48 L99 77 L99 139 L8 108 Z" fill="#232b2f" opacity=".34"/>
        <path d="M99 77 L190 48 L190 108 L99 139 Z" fill="url(#${id}-stone-side)" opacity=".58"/>
        <path d="M19 48 L99 25 L179 49 L99 71 Z" fill="#2d3539" stroke="#151c1f" stroke-width="1.6"/>
        <path d="M15 57 L99 84 L185 57 L185 107 L99 135 L15 107 Z" fill="url(#${id}-masonry)" opacity=".88"/>
        <path d="M18 59 L99 85 L181 59" fill="none" stroke="#aab1af" stroke-opacity=".34" stroke-width="1.8"/>
        <path d="M25 67 L25 109 M54 75 L54 118 M84 84 L84 128 M114 84 L114 128 M144 75 L144 118 M173 67 L173 109" stroke="#6b7476" stroke-width="3" opacity=".62"/>
        ${slit(33, 76, .7)}${slit(93, 94, .7)}${slit(155, 76, .7)}
        <path d="M13 104 L99 132 L186 104" fill="none" stroke="#101618" stroke-width="3" stroke-opacity=".7"/>
        ${rear}${front}${ornaments}${fires}${royal ? crest(99, 99, true) : ''}
      </g>
    </svg>`;
  }

  function towerArt(level) {
    const tier = clampLevel(level);
    const id = nextId('tower');
    const royal = tier >= 5;
    const topRear = [34, 62, 90, 118, 146].map((x, i) => merlon(x, 54 + (i % 2) * .5, 1)).join('');
    const topFront = [46, 74, 102, 130].map((x, i) => merlon(x, 76 + (i % 2) * .5, .9)).join('');
    const moat = tier >= 4
      ? `<ellipse cx="102" cy="222" rx="77" ry="17" fill="url(#${id}-water)" opacity=".88"/><path d="M39 220 Q102 206 165 220" fill="none" stroke="#c3eef1" stroke-width="1.8" stroke-opacity=".58"/>`
      : '';
    const fires = tier >= 2 ? `${torch(52, 149, id)}${torch(152, 140, id, true)}` : '';
    const sideFlags = tier >= 3 ? `${banner(39, 64, id, 1, royal, .5)}${banner(165, 61, id, -1, royal, .5)}` : '';

    return `<svg viewBox="0 0 204 242" aria-hidden="true">
      ${defs(id)}
      <g filter="url(#${id}-shadow)">
        ${moat}
        <ellipse cx="102" cy="219" rx="70" ry="14" fill="#090f11" opacity=".43"/>
        <path d="M34 80 L102 56 L170 80 L170 190 L145 211 L102 231 L59 211 L34 190 Z" fill="url(#${id}-stone-front)" stroke="#171e21" stroke-width="2.8" filter="url(#${id}-stone-noise)"/>
        <path d="M34 80 L102 56 L170 80 L102 106 Z" fill="url(#${id}-stone-top)" stroke="#293134" stroke-width="2.1"/>
        <path d="M34 80 L102 106 L102 231 L59 211 L34 190 Z" fill="#232b2f" opacity=".37"/>
        <path d="M102 106 L170 80 L170 190 L145 211 L102 231 Z" fill="url(#${id}-stone-side)" opacity=".58"/>
        <path d="M47 81 L102 62 L157 81 L102 101 Z" fill="#2b3438" stroke="#151c1f" stroke-width="1.6"/>
        <path d="M41 91 L102 113 L163 91 L163 188 L143 204 L102 223 L61 204 L41 188 Z" fill="url(#${id}-masonry)" opacity=".9"/>
        <path d="M48 111 H156 M45 139 H159 M43 167 H161 M51 193 H153" stroke="#151c1f" stroke-opacity=".44" stroke-width="1.15"/>
        <path d="M63 98 V124 M92 107 V136 M122 107 V136 M151 98 V124 M58 139 V166 M86 148 V178 M117 148 V178 M146 139 V166 M70 173 V203 M102 182 V216 M134 173 V203" stroke="#717a7c" stroke-width="2.4" opacity=".58"/>
        <path d="M86 159 Q102 126 118 159 V216 H86 Z" fill="#12191b" stroke="#909897" stroke-width="2.3"/>
        <path d="M91 165 Q102 143 113 165 V211 H91 Z" fill="#070b0c"/>
        <path d="M93 175H111 M93 188H111 M93 201H111" stroke="#4c5558" stroke-width="2"/>
        ${slit(58, 128, .82)}${slit(136, 120, .82)}
        ${topRear}${topFront}${banner(102, 0, id, 1, royal, .92)}${sideFlags}${fires}${royal ? crest(102, 129, true) : ''}
      </g>
    </svg>`;
  }

  function gateTower(x, y, id, mirror = false, royal = false, tier = 1) {
    const rear = [0, 27, 54].map((dx, i) => merlon(dx, 34 + (i % 2) * .5, .86)).join('');
    const front = [10, 37].map((dx, i) => merlon(dx, 50 + (i % 2) * .5, .78)).join('');
    return `<g transform="translate(${x} ${y}) ${mirror ? 'scale(-1 1)' : ''}">
      <path d="M0 47 L34 35 L68 47 L68 143 L34 163 L0 143 Z" fill="url(#${id}-stone-front)" stroke="#171e21" stroke-width="2.2"/>
      <path d="M0 47 L34 35 L68 47 L34 60 Z" fill="url(#${id}-stone-top)" stroke="#293134" stroke-width="1.7"/>
      <path d="M7 57 L34 66 L61 57 L61 140 L34 155 L7 140 Z" fill="url(#${id}-masonry)" opacity=".9"/>
      <path d="M13 83H55 M11 109H57 M13 135H55" stroke="#171e21" stroke-width="1" stroke-opacity=".55"/>
      ${slit(16, 91, .7)}${slit(43, 80, .7)}
      ${rear}${front}
      ${tier >= 3 ? banner(34, -12, id, mirror ? -1 : 1, royal, .62) : ''}
    </g>`;
  }

  function gateArt(level) {
    const tier = clampLevel(level);
    const id = nextId('gate');
    const royal = tier >= 5;
    const moat = tier >= 4
      ? `<path d="M20 204 Q142 225 264 204 L275 217 Q142 244 9 217 Z" fill="url(#${id}-water)" opacity=".9"/><path d="M23 208 Q142 226 261 208" fill="none" stroke="#c5eff1" stroke-width="1.8" stroke-opacity=".6"/>`
      : '';
    const fires = tier >= 2 ? `${torch(84, 137, id)}${torch(200, 130, id, true)}${torch(142, 82, id)}` : '';

    return `<svg viewBox="0 0 284 250" aria-hidden="true">
      ${defs(id)}
      <g filter="url(#${id}-shadow)">
        ${moat}
        <ellipse cx="142" cy="225" rx="118" ry="15" fill="#090f11" opacity=".45"/>
        ${gateTower(12, 55, id, false, royal, tier)}
        ${gateTower(272, 52, id, true, royal, tier)}
        <path d="M65 91 L142 67 L219 91 L219 184 L142 216 L65 184 Z" fill="url(#${id}-stone-front)" stroke="#171e21" stroke-width="2.8" filter="url(#${id}-stone-noise)"/>
        <path d="M65 91 L142 67 L219 91 L142 119 Z" fill="url(#${id}-stone-top)" stroke="#293134" stroke-width="2"/>
        <path d="M73 101 L142 126 L211 101 L211 180 L142 207 L73 180 Z" fill="url(#${id}-masonry)" opacity=".92"/>
        <path d="M90 143 Q142 78 194 143 V205 H90 Z" fill="#11181a" stroke="#9ba2a0" stroke-width="4"/>
        <path d="M99 148 Q142 96 185 148 V202 H99 Z" fill="url(#${id}-iron)" stroke="#252d30" stroke-width="2.8"/>
        <path d="M107 143V202 M119 128V202 M130 116V202 M142 108V202 M154 116V202 M165 128V202 M177 143V202" stroke="#151b1d" stroke-width="3.2"/>
        <path d="M99 156H185 M99 174H185 M99 192H185" stroke="#273033" stroke-width="2.4"/>
        <path d="M99 205 L185 205 L214 236 L70 236 Z" fill="url(#${id}-wood)" stroke="#251a14" stroke-width="2.8"/>
        <path d="M80 229H204 M92 213L101 236 M113 208L119 236 M142 205V236 M171 208L165 236 M192 213L183 236" stroke="#2b1d15" stroke-width="2.3" opacity=".9"/>
        <path d="M101 135 L91 84 M183 135 L193 84" stroke="#252d2f" stroke-width="2.1"/>
        <circle cx="91" cy="84" r="4.6" fill="#7e8686" stroke="#202729"/>
        <circle cx="193" cy="84" r="4.6" fill="#7e8686" stroke="#202729"/>
        ${slit(76, 127, .72)}${slit(198, 120, .72)}
        ${banner(142, 0, id, 1, royal, .82)}${fires}${royal ? crest(142, 92, true) : ''}
      </g>
    </svg>`;
  }

  globalThis.ReinosFortificationVisuals = Object.freeze({
    ...base,
    VERSION: 4,
    wallArt,
    towerArt,
    gateArt,
    metrics: Object.freeze({
      wall: Object.freeze({ width: 122, height: 96 }),
      tower: Object.freeze({ width: 165, height: 210 }),
      gate: Object.freeze({ width: 232, height: 204 })
    })
  });
})();
