import*as e from"../third_party/lit-html/lit-html.js";import{Directives as t}from"../third_party/lit-html/lit-html.js";import{SimpleHistoryManager as s}from"../common/common.js";function r(e,t){return e.toString(16).padStart(t,"0").toUpperCase()}const{render:i,html:n}=e;class o extends Event{constructor(e){super("page-navigation",{}),this.data=e}}class a extends Event{constructor(e){super("history-navigation",{}),this.data=e}}class d extends Event{constructor(){super("refresh",{})}}class l extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.address=0}set data(e){if(e.address<0)throw new Error("Address should be greater or equal to zero.");this.address=e.address,this.render()}render(){i(n`
      <style>
        .navigator {
          min-height: 24px;
          display: flex;
          flex-wrap: nowrap;
          justify-content: space-between;
          overflow: hidden;
          align-items: center;
        }

        .navigator-item {
          white-space: nowrap;
          overflow: hidden;
        }

        input {
          text-align: center;
        }

        .navigator-button {
          background: transparent;
          overflow: hidden;
          vertical-align: middle;
          border: none;
          padding: 0px;
        }
      </style>
      <div class="navigator">
        <div class="navigator-item">
          ${this.createButton("ic_undo_16x16_icon",new a("Backward"))}
          ${this.createButton("ic_redo_16x16_icon",new a("Forward"))}
        </div>
        <div class="navigator-item">
          ${this.createButton("ic_page_prev_16x16_icon",new o("Backward"))}
          <input data-input="true" contenteditable="true" value="0x${r(this.address,8)}"/>
          ${this.createButton("ic_page_next_16x16_icon",new o("Forward"))}
        </div>
        ${this.createButton("refresh_12x12_icon",new d)}
      </div>
      `,this.shadow,{eventContext:this})}createButton(e,t){return n`
      <button class="navigator-button" data-button=${t.type} @click=${this.dispatchEvent.bind(this,t)}>
        <devtools-icon .data=${{iconName:e,color:"rgb(110 110 110)",width:"16px"}}>
        </devtools-icon>
      </button>`}}customElements.define("devtools-linear-memory-inspector-navigator",l);var c=Object.freeze({__proto__:null,PageNavigationEvent:o,HistoryNavigationEvent:a,RefreshEvent:d,LinearMemoryNavigator:l});var h,m,p;function u(e,t){switch(t){case p.Decimal:return e.toFixed(2).toString();case p.Scientific:return e.toExponential(2).toString();default:throw new Error(`Unknown mode for floats: ${t}.`)}}function f(e,t){switch(t){case p.Decimal:return e.toString();case p.Hexadecimal:return e.toString(16);case p.Octal:return e.toString(8);default:throw new Error(`Unknown mode for integers: ${t}.`)}}!function(e){e.Int8="Integer 8-bit",e.Int16="Integer 16-bit",e.Int32="Integer 32-bit",e.Int64="Integer 64-bit",e.Float32="Float 32-bit",e.Float64="Float 64-bit",e.Boolean="Boolean",e.String="String"}(h||(h={})),function(e){e.Little="Little Endian",e.Big="Big Endian"}(m||(m={})),function(e){e.Decimal="dec",e.Hexadecimal="hex",e.Octal="oct",e.Scientific="sci",e.None="none"}(p||(p={}));const{render:y,html:v}=e,g=new Map([[h.Int8,p.Decimal],[h.Int16,p.Decimal],[h.Int32,p.Decimal],[h.Int64,p.Decimal],[h.Float32,p.Decimal],[h.Float64,p.Decimal],[h.Boolean,p.None],[h.String,p.None]]);class w extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.endianness=m.Little,this.buffer=new ArrayBuffer(0),this.valueTypes=[],this.valueTypeModeConfig=g}set data(e){this.buffer=e.buffer,this.valueTypes=e.valueTypes,this.valueTypeModeConfig=g,e.valueTypeModes&&e.valueTypeModes.forEach((e,t)=>{(function(e,t){switch(e){case h.Int8:case h.Int16:case h.Int32:case h.Int64:return t===p.Decimal||t===p.Hexadecimal||t===p.Octal;case h.Float32:case h.Float64:return t===p.Scientific||t===p.Decimal;case h.Boolean:case h.String:return t===p.None}})(t,e)&&this.valueTypeModeConfig.set(t,e)}),this.render()}render(){y(v`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .mode-type {
          color: var(--text-highlight-color);
        }

        .value-types {
          display: grid;
          overflow: hidden;
          grid-template-columns: minmax(90px, 1fr) minmax(25px, 0.5fr) minmax(100px, 2fr) minmax(100px, 2fr);
          grid-column-gap: 10px;
          padding-left: 12px;
          padding-right: 12px;
        }

        .value-type-cell {
          height: 21px;
          text-overflow: ellipsis;
          white-space: nowrap;
          overflow: hidden;
          display: flex;
        }

      </style>
        <div class="value-types">
          ${this.valueTypes.map(e=>this.showValue(e))}
        </div>
      </div>
    `,this.shadow,{eventContext:this})}showValue(e){return v`
      <span class="value-type-cell">${e}</span>
      ${function(e){switch(e){case h.Int8:case h.Int16:case h.Int32:case h.Int64:case h.Float32:case h.Float64:return!0;default:return!1}}(e)?v`<span class="mode-type value-type-cell">${this.valueTypeModeConfig.get(e)}</span>`:v`<span/>`}
      ${function(e){switch(e){case h.Int8:case h.Int16:case h.Int32:case h.Int64:return!0;default:return!1}}(e)?v`
        <span class="value-type-cell" data-value="true">+ ${this.parse({type:e,signed:!1})}</span>
        <span class="value-type-cell" data-value="true">± ${this.parse({type:e,signed:!0})}</span>`:v`<span class="value-type-cell" data-value="true">${this.parse({type:e})}</span>`}
    `}parse(e){const t=this.valueTypeModeConfig.get(e.type);if(!t)throw new Error("No known way of showing value for "+e.type);return function(e){const t=new DataView(e.buffer),s=e.endianness===m.Little;let r;switch(e.type){case h.Int8:return r=e.signed?t.getInt8(0):t.getUint8(0),f(r,e.mode);case h.Int16:return r=e.signed?t.getInt16(0,s):t.getUint16(0,s),f(r,e.mode);case h.Int32:return r=e.signed?t.getInt32(0,s):t.getUint32(0,s),f(r,e.mode);case h.Int64:return r=e.signed?t.getBigInt64(0,s):t.getBigUint64(0,s),f(r,e.mode);case h.Float32:return r=t.getFloat32(0,s),u(r,e.mode);case h.Float64:return r=t.getFloat64(0,s),u(r,e.mode);case h.Boolean:return""+!!(1&t.getInt8(0));case h.String:throw new Error(`Type ${e.type} is not yet implemented`)}}({buffer:this.buffer,type:e.type,endianness:this.endianness,signed:e.signed||!1,mode:t})}}customElements.define("devtools-linear-memory-inspector-interpreter-display",w);var x=Object.freeze({__proto__:null,ValueInterpreterDisplay:w});const{render:b,html:I}=e;class _ extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.endianness=m.Little,this.buffer=new ArrayBuffer(0),this.valueTypes=[],this.valueTypeModeConfig=new Map}set data(e){this.endianness=e.endianness,this.buffer=e.value,this.valueTypes=e.valueTypes,this.valueTypeModeConfig=e.valueTypeModes||new Map,this.render()}render(){b(I`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .value-interpreter {
          border: var(--divider-border, 1px solid #d0d0d0);
          background-color: var(--toolbar-bg-color, #f3f3f3);
          overflow: hidden;
          --text-highlight-color: #80868b;
        }

        .settings-toolbar {
          min-height: 26px;
          display: flex;
          flex-wrap: nowrap;
          justify-content: space-between;
          padding-left: 12px;
          padding-right: 12px
        }

        .settings-item {
          line-height: 26px;
        }

        .divider {
          display: block;
          height: 1px;
          margin-bottom: 12px;
          background-color: var(--divider-color,  #d0d0d0);
        }
      </style>
      <div class="value-interpreter">
        <div class="settings-toolbar">
          <div class="settings-item">
            <span>${this.endianness}</span>
            <devtools-icon
              .data=${{iconName:"dropdown_7x6_icon",color:"rgb(110 110 110)",width:"7px"}}>
            </devtools-icon>
          </div>
          <div class="settings-item">
            <devtools-icon
              .data=${{iconName:"settings_14x14_icon",color:"rgb(110 110 110)",width:"14px"}}>
            </devtools-icon>
          </div>
        </div>
        <span class="divider"></span>
        <devtools-linear-memory-inspector-interpreter-display
          .data=${{buffer:this.buffer,valueTypes:this.valueTypes,endianness:this.endianness,valueTypeModes:this.valueTypeModeConfig}}>
        </devtools-linear-memory-inspector-interpreter-display>
      </div>
    `,this.shadow,{eventContext:this})}}customElements.define("devtools-linear-memory-inspector-interpreter",_);var E=Object.freeze({__proto__:null,LinearMemoryValueInterpreter:_});const{render:R,html:B}=e;class O extends Event{constructor(e){super("byte-selected"),this.data=e}}class $ extends Event{constructor(e){super("resize"),this.data=e}}class M extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.resizeObserver=new ResizeObserver(()=>this.resize()),this.isObservingResize=!1,this.memory=new Uint8Array,this.address=0,this.memoryOffset=0,this.numRows=1,this.numBytesInRow=M.BYTE_GROUP_SIZE}set data(e){if(e.address<e.memoryOffset||e.address>e.memoryOffset+e.memory.length||e.address<0)throw new Error("Address is out of bounds.");if(e.memoryOffset<0)throw new Error("Memory offset has to be greater or equal to zero.");this.memory=e.memory,this.address=e.address,this.memoryOffset=e.memoryOffset,this.update()}disconnectedCallback(){this.isObservingResize=!1,this.resizeObserver.disconnect()}update(){this.updateDimensions(),this.render(),this.engageResizeObserver()}resize(){this.update(),this.dispatchEvent(new $(this.numBytesInRow*this.numRows))}updateDimensions(){if(0===this.clientWidth||0===this.clientHeight||!this.shadowRoot)return this.numBytesInRow=M.BYTE_GROUP_SIZE,void(this.numRows=1);const e=this.shadowRoot.querySelector(".byte-cell"),t=this.shadowRoot.querySelector(".text-cell"),s=this.shadowRoot.querySelector(".divider"),r=this.shadowRoot.querySelector(".row");if(!(e&&t&&s&&r))return this.numBytesInRow=M.BYTE_GROUP_SIZE,void(this.numRows=1);const i=e.getBoundingClientRect().width,n=t.getBoundingClientRect().width,o=M.BYTE_GROUP_SIZE*(i+n)+M.BYTE_GROUP_MARGIN,a=s.getBoundingClientRect().width,d=this.clientWidth-(e.getBoundingClientRect().left-this.getBoundingClientRect().left)-a;if(d<o)return this.numBytesInRow=M.BYTE_GROUP_SIZE,void(this.numRows=1);this.numBytesInRow=Math.floor(d/o)*M.BYTE_GROUP_SIZE,this.numRows=Math.floor(this.clientHeight/r.clientHeight)}engageResizeObserver(){this.resizeObserver&&!this.isObservingResize&&(this.resizeObserver.observe(this),this.isObservingResize=!0)}render(){R(B`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .view {
          overflow: hidden;
          text-overflow: ellipsis;
          box-sizing: border-box;
          --selected-cell-color: #1a1aa6;
        }

        .row {
          display: flex;
          height: 20px;
        }

        .cell {
          text-align: center;
          border: 1px solid transparent;
          border-radius: 2px;
        }

        .cell.selected {
          border-color: var(--selected-cell-color);
          color: var(--selected-cell-color);
          background-color: #cfe8fc;
        }

        .byte-cell {
          min-width: 21px;
        }

        .byte-group-margin {
          margin-left: ${M.BYTE_GROUP_MARGIN}px;
        }

        .text-cell {
          min-width: 14px;
          color: var(--selected-cell-color);
        }

        .address {
          font-size: 11px;
          color: #9aa0a6;
        }

        .address.selected {
          font-weight: bold;
          color: #333333;
        }

        .divider {
          width: 1px;
          background-color: rgb(204, 204, 204);
          margin: 0px 4px 0px 4px;
        }
      </style>
      <div class="view">
          ${this.renderView()}
      </div>
      `,this.shadow,{eventContext:this})}renderView(){const e=[];for(let t=0;t<this.numRows;++t)e.push(this.renderRow(t));return B`${e}`}renderRow(e){const{startIndex:s,endIndex:i}={startIndex:e*this.numBytesInRow,endIndex:(e+1)*this.numBytesInRow},n={address:!0,selected:Math.floor((this.address-this.memoryOffset)/this.numBytesInRow)===e};return B`
    <div class="row">
      <span class="${t.classMap(n)}">${r(s+this.memoryOffset,8)}</span>
      <span class="divider"></span>
      ${this.renderByteValues(s,i)}
      <span class="divider"></span>
      ${this.renderCharacterValues(s,i)}
    </div>
    `}renderByteValues(e,s){const i=[];for(let n=e;n<s;++n){const s={cell:!0,"byte-cell":!0,"byte-group-margin":n!==e&&(n-e)%M.BYTE_GROUP_SIZE==0,selected:n===this.address-this.memoryOffset},o=n<this.memory.length?B`${r(this.memory[n],2)}`:"";i.push(B`
        <span class="${t.classMap(s)}" @click=${this.onSelectedByte(n+this.memoryOffset)}>
          ${o}
        </span>`)}return B`${i}`}renderCharacterValues(e,s){const r=[];for(let i=e;i<s;++i){const e={cell:!0,"text-cell":!0,selected:this.address-this.memoryOffset===i},s=i<this.memory.length?B`${this.toAscii(this.memory[i])}`:"";r.push(B`<span class="${t.classMap(e)}">${s}</span>`)}return B`${r}`}toAscii(e){return e>=20&&e<=127?String.fromCharCode(e):"."}onSelectedByte(e){return()=>{this.dispatchEvent(new O(e))}}}M.BYTE_GROUP_MARGIN=8,M.BYTE_GROUP_SIZE=4,customElements.define("devtools-linear-memory-inspector-viewer",M);var T=Object.freeze({__proto__:null,ByteSelectedEvent:O,ResizeEvent:$,LinearMemoryViewer:M});const{render:S,html:z}=e;class P{constructor(e,t){if(this.address=0,e<0)throw new Error("Address should be a greater or equal to zero");this.address=e,this.callback=t}valid(){return!0}reveal(){this.callback(this.address)}}class C extends Event{constructor(e,t,s){super("memoryRequest"),this.data={start:e,end:t,address:s}}}class F extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.history=new s.SimpleHistoryManager(10),this.memory=new Uint8Array,this.memoryOffset=0,this.address=0,this.numBytesPerPage=4}set data(e){if(e.address<e.memoryOffset||e.address>e.memoryOffset+e.memory.length||e.address<0)throw new Error("Address is out of bounds.");if(e.memoryOffset<0)throw new Error("Memory offset has to be greater or equal to zero.");this.memory=e.memory,this.address=e.address,this.memoryOffset=e.memoryOffset,this.render()}render(){const{start:e,end:t}=this.getPageRangeForAddress(this.address,this.numBytesPerPage);S(z`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .memory-inspector {
          display: flex;
          flex: auto;
          flex-direction: column;
          font-family: monospace;
          padding: 9px 12px 9px 7px;
        }

        devtools-linear-memory-inspector-navigator + devtools-linear-memory-inspector-viewer {
          margin-top: 12px;
        }
      </style>
      <div class="memory-inspector">
        <devtools-linear-memory-inspector-navigator
          .data=${{address:this.address}}
          @page-navigation=${this.navigatePage}
          @history-navigation=${this.navigateHistory}></devtools-linear-memory-inspector-navigator>
        <devtools-linear-memory-inspector-viewer
          .data=${{memory:this.memory.slice(e-this.memoryOffset,t-this.memoryOffset),address:this.address,memoryOffset:e}}
          @byte-selected=${e=>this.jumpToAddress(e.data)}
          @resize=${this.resize}>
        </devtools-linear-memory-inspector-viewer>
      </div>
      <devtools-linear-memory-inspector-interpreter .data=${{value:this.memory.slice(this.address-this.memoryOffset,this.address+8).buffer,valueTypes:[h.Int8,h.Int16,h.Int64],endianness:m.Little}}>
      </devtools-linear-memory-inspector-interpreter/>
      `,this.shadow,{eventContext:this})}navigateHistory(e){return"Forward"===e.data?this.history.rollover():this.history.rollback()}navigatePage(e){const t="Forward"===e.data?this.address+this.numBytesPerPage:Math.max(this.address-this.numBytesPerPage,0);this.jumpToAddress(t)}jumpToAddress(e){const t=new P(e,e=>this.jumpToAddress(e));this.history.push(t),this.address=e,this.update()}getPageRangeForAddress(e,t){const s=Math.floor(e/t)*t;return{start:s,end:s+t}}resize(e){this.numBytesPerPage=e.data,this.update()}update(){const{start:e,end:t}=this.getPageRangeForAddress(this.address,this.numBytesPerPage);e<this.memoryOffset||t>this.memoryOffset+this.memory.length?this.dispatchEvent(new C(e,t,this.address)):this.render()}}customElements.define("devtools-linear-memory-inspector-inspector",F);var A=Object.freeze({__proto__:null,MemoryRequestEvent:C,LinearMemoryInspector:F});export{A as LinearMemoryInspector,c as LinearMemoryNavigator,E as LinearMemoryValueInterpreter,T as LinearMemoryViewer,x as ValueInterpreterDisplay};
