import*as UI from"../../ui/ui.js";import{BottomPaddingWithoutParam,BottomPaddingWithParam,LeftMarginOfText,LeftSideTopPadding,NodeLabelFontStyle,ParamLabelFontStyle,PortTypes,RightMarginOfText,TotalInputPortHeight,TotalOutputPortHeight,TotalParamPortHeight}from"./GraphStyle.js";import{calculateInputPortXY,calculateOutputPortXY,calculateParamPortXY}from"./NodeRendererUtility.js";export class NodeView{constructor(t,e){this.id=t.nodeId,this.type=t.nodeType,this.numberOfInputs=t.numberOfInputs,this.numberOfOutputs=t.numberOfOutputs,this.label=e,this.size={width:0,height:0},this.position=null,this._layout={inputPortSectionHeight:0,outputPortSectionHeight:0,maxTextLength:0,totalHeight:0},this.ports=new Map,this._initialize(t)}_initialize(t){this._updateNodeLayoutAfterAddingNode(t),this._setupInputPorts(),this._setupOutputPorts()}addParamPort(t,e){const o=this.getPortsByType(PortTypes.Param).length,{x:a,y:i}=calculateParamPortXY(o,this._layout.inputPortSectionHeight);this._addPort({id:generateParamPortId(this.id,t),type:PortTypes.Param,label:e,x:a,y:i}),this._updateNodeLayoutAfterAddingParam(o+1,e),this._setupOutputPorts()}getPortsByType(t){const e=[];return this.ports.forEach((o=>{o.type===t&&e.push(o)})),e}_updateNodeLayoutAfterAddingNode(t){const e=TotalInputPortHeight*Math.max(1,t.numberOfInputs)+LeftSideTopPadding;this._layout.inputPortSectionHeight=e,this._layout.outputPortSectionHeight=TotalOutputPortHeight*t.numberOfOutputs,this._layout.totalHeight=Math.max(e+BottomPaddingWithoutParam,this._layout.outputPortSectionHeight);const o=measureTextWidth(this.label,NodeLabelFontStyle);this._layout.maxTextLength=Math.max(this._layout.maxTextLength,o),this._updateNodeSize()}_updateNodeLayoutAfterAddingParam(t,e){const o=this._layout.inputPortSectionHeight+t*TotalParamPortHeight+BottomPaddingWithParam;this._layout.totalHeight=Math.max(o,this._layout.outputPortSectionHeight);const a=measureTextWidth(e,ParamLabelFontStyle);this._layout.maxTextLength=Math.max(this._layout.maxTextLength,a),this._updateNodeSize()}_updateNodeSize(){this.size={width:Math.ceil(LeftMarginOfText+this._layout.maxTextLength+RightMarginOfText),height:this._layout.totalHeight}}_setupInputPorts(){for(let t=0;t<this.numberOfInputs;t++){const{x:e,y:o}=calculateInputPortXY(t);this._addPort({id:generateInputPortId(this.id,t),type:PortTypes.In,x:e,y:o,label:void 0})}}_setupOutputPorts(){for(let t=0;t<this.numberOfOutputs;t++){const e=generateOutputPortId(this.id,t),{x:o,y:a}=calculateOutputPortXY(t,this.size,this.numberOfOutputs);if(this.ports.has(e)){const t=this.ports.get(e);if(!t)throw new Error(`Unable to find port with id ${e}`);t.x=o,t.y=a}else this._addPort({id:e,type:PortTypes.Out,x:o,y:a,label:void 0})}}_addPort(t){this.ports.set(t.id,t)}}export const generateInputPortId=(t,e)=>`${t}-input-${e||0}`;export const generateOutputPortId=(t,e)=>`${t}-output-${e||0}`;export const generateParamPortId=(t,e)=>`${t}-param-${e}`;export class NodeLabelGenerator{constructor(){this._totalNumberOfNodes=0}generateLabel(t){t.endsWith("Node")&&(t=t.slice(0,t.length-4)),this._totalNumberOfNodes+=1;return`${t} ${this._totalNumberOfNodes}`}}let _contextForFontTextMeasuring;export const measureTextWidth=(t,e)=>{if(!_contextForFontTextMeasuring){const t=document.createElement("canvas").getContext("2d");if(!t)throw new Error("Unable to create canvas context.");_contextForFontTextMeasuring=t}const o=_contextForFontTextMeasuring;o.save(),e&&(o.font=e);const a=UI.UIUtils.measureTextWidth(o,t);return o.restore(),a};