import"./LinearMemoryNavigator.js";import"./LinearMemoryValueInterpreter.js";import"./LinearMemoryViewer.js";import*as Common from"../common/common.js";import*as LitHtml from"../third_party/lit-html/lit-html.js";const{render:render,html:html}=LitHtml;import{VALUE_INTEPRETER_MAX_NUM_BYTES,DEFAULT_MODE_MAPPING}from"./ValueInterpreterDisplayUtils.js";import{formatAddress,parseAddress}from"./LinearMemoryInspectorUtils.js";import*as i18n from"../i18n/i18n.js";const UIStrings={addressHasToBeANumberBetweenSAnd:"Address has to be a number between {PH1} and {PH2}"},str_=i18n.i18n.registerUIStrings("linear_memory_inspector/LinearMemoryInspector.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);class AddressHistoryEntry{constructor(e,s){if(this.address=0,e<0)throw new Error("Address should be a greater or equal to zero");this.address=e,this.callback=s}valid(){return!0}reveal(){this.callback(this.address)}}export class MemoryRequestEvent extends Event{constructor(e,s,t){super("memory-request"),this.data={start:e,end:s,address:t}}}export class AddressChangedEvent extends Event{constructor(e){super("address-changed"),this.data=e}}export class LinearMemoryInspector extends HTMLElement{constructor(){super(...arguments),this.shadow=this.attachShadow({mode:"open"}),this.history=new Common.SimpleHistoryManager.SimpleHistoryManager(10),this.memory=new Uint8Array,this.memoryOffset=0,this.outerMemoryLength=0,this.address=0,this.currentNavigatorMode="Submitted",this.currentNavigatorAddressLine=`${this.address}`,this.numBytesPerPage=4,this.valueTypes=new Set(DEFAULT_MODE_MAPPING.keys()),this.valueTypeModes=DEFAULT_MODE_MAPPING,this.endianness="Little Endian"}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.memoryOffset=e.memoryOffset,this.outerMemoryLength=e.outerMemoryLength,this.setAddress(e.address),this.render()}render(){const{start:e,end:s}=this.getPageRangeForAddress(this.address,this.numBytesPerPage),t="Submitted"===this.currentNavigatorMode?formatAddress(this.address):this.currentNavigatorAddressLine,r=this.isValidAddress(t),i=i18nString(UIStrings.addressHasToBeANumberBetweenSAnd,{PH1:formatAddress(0),PH2:formatAddress(this.outerMemoryLength)}),o=r?void 0:i;render(html`
      <style>
        :host {
          flex: auto;
          display: flex;
        }

        .view {
          width: 100%;
          display: flex;
          flex: 1;
          flex-direction: column;
          font-family: var(--monospace-font-family);
          font-size: var(--monospace-font-size);
          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:t,valid:r,mode:this.currentNavigatorMode,error:o}}
          @refresh-requested=${this.onRefreshRequest}
          @address-input-changed=${this.onAddressChange}
          @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,s-this.memoryOffset),address:this.address,memoryOffset:e,focus:"Submitted"===this.currentNavigatorMode}}
          @byte-selected=${this.onByteSelected}
          @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+VALUE_INTEPRETER_MAX_NUM_BYTES).buffer,valueTypes:this.valueTypes,valueTypeModes:this.valueTypeModes,endianness:this.endianness}}
          @value-type-toggled=${this.onValueTypeToggled}
          @value-type-mode-changed=${this.onValueTypeModeChanged}
          @endianness-changed=${this.onEndiannessChanged}>
        </devtools-linear-memory-inspector-interpreter/>
      </div>
      `,this.shadow,{eventContext:this})}onRefreshRequest(){const{start:e,end:s}=this.getPageRangeForAddress(this.address,this.numBytesPerPage);this.dispatchEvent(new MemoryRequestEvent(e,s,this.address))}onByteSelected(e){this.currentNavigatorMode="Submitted";const s=Math.max(0,Math.min(e.data,this.outerMemoryLength-1));this.jumpToAddress(s)}onEndiannessChanged(e){this.endianness=e.data,this.render()}isValidAddress(e){const s=parseAddress(e);return void 0!==s&&s>=0&&s<this.outerMemoryLength}onAddressChange(e){const{address:s,mode:t}=e.data,r=this.isValidAddress(s),i=parseAddress(s);if(this.currentNavigatorAddressLine=s,void 0!==i&&r)return this.currentNavigatorMode=t,void this.jumpToAddress(i);this.currentNavigatorMode="Submitted"!==t||r?"Edit":"InvalidSubmit",this.render()}onValueTypeToggled(e){const{type:s,checked:t}=e.data;t?this.valueTypes.add(s):this.valueTypes.delete(s),this.render()}onValueTypeModeChanged(e){e.stopImmediatePropagation();const{type:s,mode:t}=e.data;this.valueTypeModes.set(s,t),this.render()}navigateHistory(e){return"Forward"===e.data?this.history.rollover():this.history.rollback()}navigatePage(e){const s="Forward"===e.data?this.address+this.numBytesPerPage:this.address-this.numBytesPerPage,t=Math.max(0,Math.min(s,this.outerMemoryLength-1));this.jumpToAddress(t)}jumpToAddress(e){e<0||e>=this.outerMemoryLength?console.warn(`Specified address is out of bounds: ${e}`):(this.setAddress(e),this.update())}getPageRangeForAddress(e,s){const t=Math.floor(e/s)*s;return{start:t,end:Math.min(t+s,this.outerMemoryLength)}}resize(e){this.numBytesPerPage=e.data,this.update()}update(){const{start:e,end:s}=this.getPageRangeForAddress(this.address,this.numBytesPerPage);e<this.memoryOffset||s>this.memoryOffset+this.memory.length?this.dispatchEvent(new MemoryRequestEvent(e,s,this.address)):this.render()}setAddress(e){const s=new AddressHistoryEntry(e,(()=>this.jumpToAddress(e)));this.history.push(s),this.address=e,this.dispatchEvent(new AddressChangedEvent(this.address))}}customElements.define("devtools-linear-memory-inspector-inspector",LinearMemoryInspector);