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()}var n=Object.freeze({__proto__:null,toHexString:r});const{render:i,html:o}=e;class a extends Event{constructor(e){super("page-navigation",{}),this.data=e}}class l extends Event{constructor(e){super("history-navigation",{}),this.data=e}}class d extends Event{constructor(){super("refresh",{})}}class c 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(o`
      <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 l("Backward"))}
          ${this.createButton("ic_redo_16x16_icon",new l("Forward"))}
        </div>
        <div class="navigator-item">
          ${this.createButton("ic_page_prev_16x16_icon",new a("Backward"))}
          <input data-input="true" contenteditable="true" value="0x${r(this.address,8)}"/>
          ${this.createButton("ic_page_next_16x16_icon",new a("Forward"))}
        </div>
        ${this.createButton("refresh_12x12_icon",new d)}
      </div>
      `,this.shadow,{eventContext:this})}createButton(e,t){return o`
      <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",c);var h=Object.freeze({__proto__:null,PageNavigationEvent:a,HistoryNavigationEvent:l,RefreshEvent:d,LinearMemoryNavigator:c});var p,u,m;function g(e,t){switch(e){case p.Int8:case p.Int16:case p.Int32:case p.Int64:return t===m.Decimal||t===m.Hexadecimal||t===m.Octal;case p.Float32:case p.Float64:return t===m.Scientific||t===m.Decimal;case p.Boolean:case p.String:return t===m.None}}function y(e){switch(e){case p.Int8:case p.Int16:case p.Int32:case p.Int64:return!0;default:return!1}}function v(e){switch(e){case p.Int8:case p.Int16:case p.Int32:case p.Int64:case p.Float32:case p.Float64:return!0;default:return!1}}function f(e){const t=new DataView(e.buffer),s=e.endianness===u.Little;let r;switch(e.type){case p.Int8:return r=e.signed?t.getInt8(0):t.getUint8(0),b(r,e.mode);case p.Int16:return r=e.signed?t.getInt16(0,s):t.getUint16(0,s),b(r,e.mode);case p.Int32:return r=e.signed?t.getInt32(0,s):t.getUint32(0,s),b(r,e.mode);case p.Int64:return r=e.signed?t.getBigInt64(0,s):t.getBigUint64(0,s),b(r,e.mode);case p.Float32:return r=t.getFloat32(0,s),x(r,e.mode);case p.Float64:return r=t.getFloat64(0,s),x(r,e.mode);case p.Boolean:return w(t.getInt8(0));case p.String:throw new Error(`Type ${e.type} is not yet implemented`)}}function w(e){return""+!!(1&e)}function x(e,t){switch(t){case m.Decimal:return e.toFixed(2).toString();case m.Scientific:return e.toExponential(2).toString();default:throw new Error(`Unknown mode for floats: ${t}.`)}}function b(e,t){switch(t){case m.Decimal:return e.toString();case m.Hexadecimal:return e.toString(16);case m.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"}(p||(p={})),function(e){e.Little="Little Endian",e.Big="Big Endian"}(u||(u={})),function(e){e.Decimal="dec",e.Hexadecimal="hex",e.Octal="oct",e.Scientific="sci",e.None="none"}(m||(m={}));var T=Object.freeze({__proto__:null,VALUE_INTEPRETER_MAX_NUM_BYTES:8,get ValueType(){return p},get Endianness(){return u},get ValueTypeMode(){return m},isValidMode:g,typeHasSignedNotation:y,isNumber:v,format:f,formatBoolean:w,formatFloat:x,formatInteger:b});const{render:_,html:I}=e,E=new Map([[p.Int8,m.Decimal],[p.Int16,m.Decimal],[p.Int32,m.Decimal],[p.Int64,m.Decimal],[p.Float32,m.Decimal],[p.Float64,m.Decimal],[p.Boolean,m.None],[p.String,m.None]]),$=Array.from(E.keys());class B extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.endianness=u.Little,this.buffer=new ArrayBuffer(0),this.valueTypes=new Set,this.valueTypeModeConfig=E}set data(e){this.buffer=e.buffer,this.valueTypes=e.valueTypes,this.valueTypeModeConfig=E,e.valueTypeModes&&e.valueTypeModes.forEach((e,t)=>{g(t,e)&&this.valueTypeModeConfig.set(t,e)}),this.render()}render(){_(I`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

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

        .value-types {
          display: table;
          overflow: hidden;
          padding-left: 12px;
          padding-right: 12px;
        }

        td {
          padding: 0px 24px 0px 0px;
        }

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

      </style>
        <div class="value-types">
          ${$.map(e=>this.valueTypes.has(e)?this.showValue(e):"")}
        </div>
      </div>
    `,this.shadow,{eventContext:this})}showValue(e){return I`
      <tr>
        <td colspan="${v(e)?1:2}">
          <span class="value-type-cell">${e}</span>
        </td>

        ${v(e)?I`<td><span class="mode-type value-type-cell">${this.valueTypeModeConfig.get(e)}</span></td>`:""}

        ${y(e)?I`
          <td>
            <span class="value-type-cell" data-value="true">+ ${this.parse({type:e,signed:!1})}</span>
          </td>
          <td>
            <span class="value-type-cell" data-value="true">± ${this.parse({type:e,signed:!0})}</span>
          </td>`:I`
          <td colspan="2">
            <span class="value-type-cell" data-value="true">${this.parse({type:e})}</span>
          </td>`}
      </tr>
    `}parse(e){const t=this.valueTypeModeConfig.get(e.type);if(!t)throw new Error("No known way of showing value for "+e.type);return f({buffer:this.buffer,type:e.type,endianness:this.endianness,signed:e.signed||!1,mode:t})}}customElements.define("devtools-linear-memory-inspector-interpreter-display",B);var O=Object.freeze({__proto__:null,ValueInterpreterDisplay:B});const{render:R,html:S}=e;var M;!function(e){e.Integer="Integer",e.Float="Floating point",e.Other="Other"}(M||(M={}));const z=new Map([[M.Integer,[p.Int8,p.Int16,p.Int32,p.Int64]],[M.Float,[p.Float32,p.Float64]],[M.Other,[p.Boolean,p.String]]]);class P extends Event{constructor(e,t){super("type-toggle"),this.data={type:e,checked:t}}}class F extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.valueTypes=new Set}set data(e){this.valueTypes=e.valueTypes,this.render()}render(){R(S`
      <style>
        :host {
          flex: auto;
          display: flex;
          min-height: 20px;
        }

        .settings {
          display: flex;
          flex-wrap: wrap;
          margin: 0px 12px 12px 12px;
          column-gap: 45px;
          row-gap: 15px;
        }

        .value-types-selection {
          display: flex;
          flex-direction: column;
        }

        .value-types-selection + value-types-selection {
          margin-left: 45px;
        }

        .group {
          font-weight: bold;
          margin-bottom: 11px;
        }

        .type-label {
          white-space: nowrap;
        }

        .group + .type-label {
          margin-top: 5px;
        }

        .type-label input {
          margin: 0 6px 0 0;
          padding: 0;
        }

        .type-label + .type-label {
          margin-top: 6px;
        }
      </style>
      <div class="settings">
       ${[...z.keys()].map(e=>S`
          <div class="value-types-selection">
            <span class="group">${e}</span>
            ${this.plotTypeSelections(e)}
          </div>
        `)}
      </div>
      `,this.shadow,{eventContext:this})}plotTypeSelections(e){const t=z.get(e);if(!t)throw new Error("Unknown group "+e);return S`
      ${t.map(e=>S`
          <label class="type-label" title=${e}>
            <input data-input="true" type="checkbox" .checked=${this.valueTypes.has(e)} @change=${t=>this.onTypeToggle(e,t)}>
            <span data-title="true">${e}</span>
          </label>
     `)}`}onTypeToggle(e,t){const s=t.target;this.dispatchEvent(new P(e,s.checked))}}customElements.define("devtools-linear-memory-inspector-interpreter-settings",F);var k=Object.freeze({__proto__:null,TypeToggleEvent:P,ValueInterpreterSettings:F});const{render:C,html:V}=e;class A extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.endianness=u.Little,this.buffer=new ArrayBuffer(0),this.valueTypes=new Set,this.valueTypeModeConfig=new Map,this.showSettings=!1}set data(e){this.endianness=e.endianness,this.buffer=e.value,this.valueTypes=e.valueTypes,this.valueTypeModeConfig=e.valueTypeModes||new Map,this.render()}render(){C(V`
      <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;
          width: 400px;
        }

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

        .settings-toolbar-button {
          display: flex;
          justify-content: center;
          width: 30px;
          height: 20px;
        }

        .divider {
          display: block;
          height: 1px;
          margin-bottom: 12px;
          background-color: var(--divider-color,  #d0d0d0);
        }
      </style>
      <div class="value-interpreter">
        <div class="settings-toolbar">
          <div>
            <span>${this.endianness}</span>
            <devtools-icon
              .data=${{iconName:"dropdown_7x6_icon",color:"rgb(110 110 110)",width:"7px"}}>
            </devtools-icon>
          </div>
          <button data-settings="true" class="settings-toolbar-button" title="Toggle value type settings" @click=${this.onSettingsToggled}>
            <devtools-icon
              .data=${{iconName:"settings_14x14_icon",color:"rgb(110 110 110)",width:"14px"}}>
            </devtools-icon>
          </button>
        </div>
        <span class="divider"></span>
        <div>
          ${this.showSettings?V`
              <devtools-linear-memory-inspector-interpreter-settings
                .data=${{valueTypes:this.valueTypes}}
                @type-toggle=${this.onTypeToggle}>
              </devtools-linear-memory-inspector-interpreter-settings>`:V`
              <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>
      </div>
    `,this.shadow,{eventContext:this})}onSettingsToggled(){this.showSettings=!this.showSettings,this.render()}onTypeToggle(e){this.dispatchEvent(new U(e.data.type,e.data.checked))}}class U extends Event{constructor(e,t){super("value-type-toggle"),this.data={type:e,checked:t}}}customElements.define("devtools-linear-memory-inspector-interpreter",A);var L=Object.freeze({__proto__:null,LinearMemoryValueInterpreter:A,ValueTypeToggleEvent:U});const{render:N,html:j}=e;class H extends Event{constructor(e){super("byte-selected"),this.data=e}}class D extends Event{constructor(e){super("resize"),this.data=e}}class G 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=G.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 D(this.numBytesInRow*this.numRows))}updateDimensions(){if(0===this.clientWidth||0===this.clientHeight||!this.shadowRoot)return this.numBytesInRow=G.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=G.BYTE_GROUP_SIZE,void(this.numRows=1);const n=e.getBoundingClientRect().width,i=t.getBoundingClientRect().width,o=G.BYTE_GROUP_SIZE*(n+i)+G.BYTE_GROUP_MARGIN,a=s.getBoundingClientRect().width,l=this.clientWidth-(e.getBoundingClientRect().left-this.getBoundingClientRect().left)-a;if(l<o)return this.numBytesInRow=G.BYTE_GROUP_SIZE,void(this.numRows=1);this.numBytesInRow=Math.floor(l/o)*G.BYTE_GROUP_SIZE,this.numRows=Math.floor(this.clientHeight/r.clientHeight)}engageResizeObserver(){this.resizeObserver&&!this.isObservingResize&&(this.resizeObserver.observe(this),this.isObservingResize=!0)}render(){N(j`
      <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: ${G.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 j`${e}`}renderRow(e){const{startIndex:s,endIndex:n}={startIndex:e*this.numBytesInRow,endIndex:(e+1)*this.numBytesInRow},i={address:!0,selected:Math.floor((this.address-this.memoryOffset)/this.numBytesInRow)===e};return j`
    <div class="row">
      <span class="${t.classMap(i)}">${r(s+this.memoryOffset,8)}</span>
      <span class="divider"></span>
      ${this.renderByteValues(s,n)}
      <span class="divider"></span>
      ${this.renderCharacterValues(s,n)}
    </div>
    `}renderByteValues(e,s){const n=[];for(let i=e;i<s;++i){const s={cell:!0,"byte-cell":!0,"byte-group-margin":i!==e&&(i-e)%G.BYTE_GROUP_SIZE==0,selected:i===this.address-this.memoryOffset},o=i<this.memory.length?j`${r(this.memory[i],2)}`:"";n.push(j`
        <span class="${t.classMap(s)}" @click=${this.onSelectedByte(i+this.memoryOffset)}>
          ${o}
        </span>`)}return j`${n}`}renderCharacterValues(e,s){const r=[];for(let n=e;n<s;++n){const e={cell:!0,"text-cell":!0,selected:this.address-this.memoryOffset===n},s=n<this.memory.length?j`${this.toAscii(this.memory[n])}`:"";r.push(j`<span class="${t.classMap(e)}">${s}</span>`)}return j`${r}`}toAscii(e){return e>=20&&e<=127?String.fromCharCode(e):"."}onSelectedByte(e){return()=>{this.dispatchEvent(new H(e))}}}G.BYTE_GROUP_MARGIN=8,G.BYTE_GROUP_SIZE=4,customElements.define("devtools-linear-memory-inspector-viewer",G);var Y=Object.freeze({__proto__:null,ByteSelectedEvent:H,ResizeEvent:D,LinearMemoryViewer:G});const{render:q,html:Z}=e;class W{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 X extends Event{constructor(e,t,s){super("memory-request"),this.data={start:e,end:t,address:s}}}class J 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,this.valueTypes=new Set([p.Int8,p.Float32,p.Boolean])}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);q(Z`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .view {
          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;
        }

        .value-interpreter {
          display: flex;
        }
      </style>
      <div class="view">
        <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>
      <div class="value-interpreter">
        <devtools-linear-memory-inspector-interpreter
          .data=${{value:this.memory.slice(this.address-this.memoryOffset,this.address+8).buffer,valueTypes:this.valueTypes,endianness:u.Little}}
          @value-type-toggle=${this.onValueTypeToggled}>
        </devtools-linear-memory-inspector-interpreter/>
      </div>
      `,this.shadow,{eventContext:this})}onValueTypeToggled(e){const{type:t,checked:s}=e.data;s?this.valueTypes.add(t):this.valueTypes.delete(t),this.render()}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 W(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 X(e,t,this.address)):this.render()}}customElements.define("devtools-linear-memory-inspector-inspector",J);var K=Object.freeze({__proto__:null,MemoryRequestEvent:X,LinearMemoryInspector:J});export{K as LinearMemoryInspector,n as LinearMemoryInspectorUtils,h as LinearMemoryNavigator,L as LinearMemoryValueInterpreter,Y as LinearMemoryViewer,O as ValueInterpreterDisplay,T as ValueInterpreterDisplayUtils,k as ValueInterpreterSettings};
