
class PhysicalPositionMenu {

  // 1) Server-side: provide the option groups
  getAllMenuData() {
    return {
      positionGroups: [
        { group: 'Positional', options: [
            { value: 'upstream',     label: '→ Upstream', icon: '→'}, //flow is then typically left to right
            { value: 'atEquipment',  label: '⊥ in place' , icon: '⊥' },
            { value: 'downstream',   label: '← Downstream' , icon: '←' }
          ]
        }
      ],
      // Distance contexts for each position
      distanceContexts: {
        upstream: {
          description: 'Distance from parent inlet',
          placeholder: 'e.g., 2.5 (meters before parent)',
          helpText: 'How far upstream from the parent equipment'
        },
        downstream: {
          description: 'Distance from parent outlet', 
          placeholder: 'e.g., 3.0 (meters after parent)',
          helpText: 'How far downstream from the parent equipment'
        },
        atEquipment: {
          description: 'Distance from parent start',
          placeholder: 'e.g., 1.2 (meters from start)', 
          helpText: 'Position within the parent equipment boundaries'
        }
      }
    };
  }

  // 2) HTML template (pure markup)
  getHtmlTemplate() {
    return `
    <hr />
    <h3>Physical Position vs parent</h3>
      <div class="form-row">
        <label for="node-input-positionVsParent"><i class="fa fa-map-marker"></i>Position</label>
        <select id="node-input-positionVsParent" style="width:70%;">
          <!-- optgroups will be injected -->
        </select>
      </div>

      <!-- Distance section -->
      <div class="form-row">
        <label>&nbsp;</label>
        <input type="checkbox" id="node-input-hasDistance" style="display:inline-block; width:auto; margin-right:5px;">
        <label for="node-input-hasDistance" style="width:auto;">Specify 1D Distance</label>
      </div>
      
      <div id="distance-section" class="form-row" style="display:none;">
        <label for="node-input-distance"><i class="fa fa-ruler"></i>Distance</label>
        <div style="display:flex; align-items:center; width:70%;">
          <input type="number" id="node-input-distance" step="0.1" min="0" style="width:60%;" placeholder="0.0">
          <span style="margin-left:5px; margin-right:5px;">meters</span>
        </div>
        <div id="distance-help" class="form-tips" style="margin-left:105px; font-size:11px; color:#666;">
          Select a position to see distance context
        </div>
      </div>
    <hr />
    `;
  }

  // 3) HTML injector
  getHtmlInjectionCode(nodeName) {
    const tpl = this.getHtmlTemplate()
      .replace(/`/g,'\\`').replace(/\$/g,'\\$');
    return `
      // PhysicalPosition HTML injection for ${nodeName}
      window.EVOLV.nodes.${nodeName}.positionMenu.injectHtml = function() {
        const ph = document.getElementById('position-fields-placeholder');
        if (ph && !ph.hasChildNodes()) {
          ph.innerHTML = \`${tpl}\`;
        }
      };
    `;
  }

  // 4) Data-loader injector
  getDataInjectionCode(nodeName) {
    return `
      // PhysicalPosition data loader for ${nodeName}
      window.EVOLV.nodes.${nodeName}.positionMenu.loadData = function(node) {
        const data = window.EVOLV.nodes.${nodeName}.menuData.position;
        const sel  = document.getElementById('node-input-positionVsParent');
        const hasDistanceCheck = document.getElementById('node-input-hasDistance');
        const distanceInput = document.getElementById('node-input-distance');
        const distanceSection = document.getElementById('distance-section');
        
        //Load position options
        if (sel) {
          sel.innerHTML = '';
          (data.positionGroups||[]).forEach(grp => {
            const optg = document.createElement('optgroup');
            optg.label = grp.group;
            grp.options.forEach(o=>{
              const opt = document.createElement('option');
              opt.value = o.value;
              opt.textContent = o.label;
              opt.setAttribute('data-icon', o.icon);
              optg.appendChild(opt);
            });
            sel.appendChild(optg);
          });
          sel.value = node.positionVsParent || 'atEquipment';
        }
        
        //Load distance values
        if (hasDistanceCheck) {
          hasDistanceCheck.checked = node.hasDistance || false;
          distanceSection.style.display = hasDistanceCheck.checked ? 'block' : 'none';
        }
        
        if (distanceInput) {
          distanceInput.value = node.distance || '';
        }
        
        // Update distance context for current position
        this.updateDistanceContext(node.positionVsParent || 'atEquipment', data.distanceContexts);
      };
    `;
  }

  // 5) (no special events needed, but stub for symmetry)
  getEventInjectionCode(nodeName) {
    return `
      // PhysicalPosition events for ${nodeName}
      window.EVOLV.nodes.${nodeName}.positionMenu.wireEvents = function(node) {
        const positionSel = document.getElementById('node-input-positionVsParent');
        const hasDistanceCheck = document.getElementById('node-input-hasDistance');
        const distanceSection = document.getElementById('distance-section');
        const data = window.EVOLV.nodes.${nodeName}.menuData.position;
        
        // Toggle distance section visibility
        if (hasDistanceCheck && distanceSection) {
          hasDistanceCheck.addEventListener('change', function() {
            distanceSection.style.display = this.checked ? 'block' : 'none';
            
            // Clear distance if unchecked
            if (!this.checked) {
              const distanceInput = document.getElementById('node-input-distance');
              if (distanceInput) {
                distanceInput.value = '';
              }
            }
          });
        }
        
        // Update distance context when position changes
        if (positionSel) {
          positionSel.addEventListener('change', function() {
            const position = this.value;
            window.EVOLV.nodes.${nodeName}.positionMenu.updateDistanceContext(position, data.distanceContexts);
          });
        }
      };
      
      // Helper function to update distance context
      window.EVOLV.nodes.${nodeName}.positionMenu.updateDistanceContext = function(position, contexts) {
        const distanceInput = document.getElementById('node-input-distance');
        const distanceHelp = document.getElementById('distance-help');
        
        const context = contexts && contexts[position];
        
        if (context && distanceInput && distanceHelp) {
          distanceInput.placeholder = context.placeholder || '0.0';
          distanceHelp.textContent = context.helpText || 'Enter distance in meters';
        }
      };
    `;
  }

  // 6) Save-logic injector
getSaveInjectionCode(nodeName) {
  return `
    // PhysicalPosition Save injection for ${nodeName}
    window.EVOLV.nodes.${nodeName}.positionMenu.saveEditor = function(node) {
      console.log("=== PhysicalPosition Save Debug ===");
      
      const sel = document.getElementById('node-input-positionVsParent');
      const hasDistanceCheck = document.getElementById('node-input-hasDistance');
      const distanceInput = document.getElementById('node-input-distance');
      
      console.log("→ sel element found:", !!sel);
      console.log("→ sel:", sel);
      console.log("→ sel.value:", sel ? sel.value : "NO ELEMENT");
      console.log("→ sel.selectedIndex:", sel ? sel.selectedIndex : "NO ELEMENT");
      console.log("→ sel.options:", sel ? Array.from(sel.options).map(o => ({value: o.value, text: o.textContent})) : "NO OPTIONS");
      
      if (!sel) {
        console.error("→ positionMenu.saveEditor FAILED: select element not found!");
        return false;
      }
      
      // Save existing position data
      const positionValue = sel.value;
      const selectedOption = sel.options[sel.selectedIndex];
      
      console.log("→ positionValue:", positionValue);
      console.log("→ selectedOption:", selectedOption);
      console.log("→ selectedOption.textContent:", selectedOption ? selectedOption.textContent : "NO OPTION");
      console.log("→ selectedOption data-icon:", selectedOption ? selectedOption.getAttribute('data-icon') : "NO ICON");
      
      node.positionVsParent = positionValue || 'atEquipment';
      node.positionLabel = selectedOption ? selectedOption.textContent : 'At Equipment';
      node.positionIcon = selectedOption ? selectedOption.getAttribute('data-icon') : 'fa fa-cog';
      
      console.log("→ node.positionVsParent set to:", node.positionVsParent);
      console.log("→ node.positionLabel set to:", node.positionLabel);
      
      // Save distance data
      console.log("→ hasDistanceCheck found:", !!hasDistanceCheck);
      console.log("→ hasDistanceCheck.checked:", hasDistanceCheck ? hasDistanceCheck.checked : "NO ELEMENT");
      
      node.hasDistance = hasDistanceCheck ? hasDistanceCheck.checked : false;
      
      if (node.hasDistance && distanceInput && distanceInput.value) {
        console.log("→ distanceInput.value:", distanceInput.value);
        node.distance = parseFloat(distanceInput.value) || 0;
        node.distanceUnit = 'm'; // Fixed to meters for now

        // Generate distance description based on position
        const contexts = window.EVOLV.nodes.${nodeName}.menuData.position.distanceContexts;
        const context = contexts && contexts[node.positionVsParent];
        node.distanceDescription = context ? context.description : 'Distance from parent';
        
        console.log("→ distance set to:", node.distance);
      } else {
        console.log("→ clearing distance data");
        delete node.distance;
        delete node.distanceUnit;
        delete node.distanceDescription;
      }
      
      console.log("→ positionMenu.saveEditor result: SUCCESS");
      console.log("→ final node.positionVsParent:", node.positionVsParent);
      
      return true;
    };
  `;
}

  // 7) Compose everything into one client bundle
  getClientInitCode(nodeName) {
    const htmlCode   = this.getHtmlInjectionCode(nodeName);
    const dataCode   = this.getDataInjectionCode(nodeName);
    const eventCode  = this.getEventInjectionCode(nodeName);
    const saveCode   = this.getSaveInjectionCode(nodeName);

    return `
      // --- PhysicalPositionMenu for ${nodeName} ---
      window.EVOLV.nodes.${nodeName}.positionMenu =
        window.EVOLV.nodes.${nodeName}.positionMenu || {};

      ${htmlCode}
      ${dataCode}
      ${eventCode}
      ${saveCode}

      // hook into oneditprepare
      window.EVOLV.nodes.${nodeName}.positionMenu.initEditor = function(node) {
        this.injectHtml();
        this.loadData(node);
        this.wireEvents(node);
      };
    `;
  }
}

module.exports = PhysicalPositionMenu;