// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as i18n from '../../../../core/i18n/i18n.js';
import type * as Platform from '../../../../core/platform/platform.js';
import * as SDK from '../../../../core/sdk/sdk.js';
import type * as Trace from '../../../../models/trace/trace.js';
import * as UI from '../../../../ui/legacy/legacy.js';
import * as Lit from '../../../../ui/lit/lit.js';

import baseInsightComponentStyles from './baseInsightComponent.css.js';
import {eventRef} from './EventRef.js';

const {html} = Lit;
const {widget} = UI.Widget;

interface ViewInput {
  request: Trace.Types.Events.SyntheticNetworkRequest;
  imageDataUrl: string|null;
}

type View = (input: ViewInput, output: undefined, target: HTMLElement) => void;

export const DEFAULT_VIEW: View = (input, output, target) => {
  const {
    request,
    imageDataUrl,
  } = input;

  const img = imageDataUrl ? html`<img src=${imageDataUrl} class="element-img"/>` : Lit.nothing;

  // clang-format off
  Lit.render(html`
    <style>${baseInsightComponentStyles}</style>
    <div class="image-ref">
      ${img}
      <span class="element-img-details">
        ${eventRef(request)}
        <span class="element-img-details-size">${
          i18n.ByteUtilities.bytesToString(request.args.data.decodedBodyLength ?? 0)
        }</span>
      </span>
    </div>
`, target);
  // clang-format on
};

class ImageRef extends UI.Widget.Widget {
  #view: View;
  #request?: Trace.Types.Events.SyntheticNetworkRequest;
  #imageDataUrl?: string|null;

  constructor(element?: HTMLElement, view: View = DEFAULT_VIEW) {
    super(element, {useShadowDom: true});
    this.#view = view;
  }

  set request(request: Trace.Types.Events.SyntheticNetworkRequest) {
    this.#request = request;
    this.#imageDataUrl = undefined;
    this.requestUpdate();
  }

  /**
   * This only returns a data url if the resource is currently present from the active
   * inspected page.
   */
  async #getOrCreateImageDataUrl(): Promise<string|null> {
    if (!this.#request) {
      return null;
    }

    if (this.#imageDataUrl !== undefined) {
      return this.#imageDataUrl;
    }

    const originalUrl = this.#request.args.data.url as Platform.DevToolsPath.UrlString;
    const resource = SDK.ResourceTreeModel.ResourceTreeModel.resourceForURL(originalUrl);
    if (!resource) {
      this.#imageDataUrl = null;
      return this.#imageDataUrl;
    }

    const content = await resource.requestContentData();
    if ('error' in content) {
      this.#imageDataUrl = null;
      return this.#imageDataUrl;
    }

    this.#imageDataUrl = content.asDataUrl();
    return this.#imageDataUrl;
  }

  override async performUpdate(): Promise<void> {
    if (!this.#request) {
      return;
    }

    const input: ViewInput = {
      request: this.#request,
      imageDataUrl: await this.#getOrCreateImageDataUrl(),
    };
    this.#view(input, undefined, this.contentElement);
  }
}

export function imageRef(request: Trace.Types.Events.SyntheticNetworkRequest): Lit.TemplateResult {
  return html`${widget(ImageRef, {request})}`;
}
