// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* eslint-disable @devtools/no-lit-render-outside-of-view */

import * as i18n from '../../../core/i18n/i18n.js';
import type * as SDK from '../../../core/sdk/sdk.js';
import * as Lit from '../../../ui/lit/lit.js';

import cssVariableValueViewStyles from './cssVariableValueView.css.js';

const UIStrings = {
  /**
   * @description Text for a link from custom property to its defining registration
   */
  registeredPropertyLinkTitle: 'View registered property',
  /**
   * @description Error message for a property value that failed to parse because it had an incorrect type. The message
   * is shown in a popover when hovering the property value. The `type` placeholder will be rendered as an HTML element
   * to apply some styling (color and monospace font)
   * @example {<color>} type
   */
  invalidPropertyValue: 'Invalid property value, expected type {type}',
  /**
   * @description Text displayed in a tooltip shown when hovering over a var() CSS function in the Styles pane when the custom property in this function does not exist. The parameter is the name of the property.
   * @example {--my-custom-property-name} PH1
   */
  sIsNotDefined: '{PH1} is not defined',
} as const;
const str_ = i18n.i18n.registerUIStrings('panels/elements/components/CSSVariableValueView.ts', UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
const i18nTemplate = Lit.i18nTemplate.bind(undefined, str_);

const {render, html} = Lit;

export interface RegisteredPropertyDetails {
  registration: SDK.CSSMatchedStyles.CSSRegisteredProperty;
  goToDefinition: () => void;
}

function getLinkSection(details: RegisteredPropertyDetails): Lit.TemplateResult {
  return html`<div class="registered-property-links">
            <span role="button" @click=${details?.goToDefinition} class="clickable underlined unbreakable-text">
              ${i18nString(UIStrings.registeredPropertyLinkTitle)}
            </span>
          </div>`;
}

export class CSSVariableParserError extends HTMLElement {
  readonly #shadow = this.attachShadow({mode: 'open'});

  constructor(details: RegisteredPropertyDetails) {
    super();
    this.#render(details);
  }

  #render(details: RegisteredPropertyDetails): void {
    const type = html`<span class="monospace css-property">${details.registration.syntax()}</span>`;
    render(
        html`
      <style>${cssVariableValueViewStyles}</style>
      <div class="variable-value-popup-wrapper">
        ${i18nTemplate(UIStrings.invalidPropertyValue, {type})}
        ${getLinkSection(details)}
      </div>`,
        this.#shadow, {
          host: this,
        });
  }
}

export class CSSVariableValueView extends HTMLElement {
  readonly #shadow = this.attachShadow({mode: 'open'});
  readonly variableName: string;
  #value: string|undefined;
  readonly details: RegisteredPropertyDetails|undefined;

  constructor({
    variableName,
    value,
    details,
  }: {
    variableName: string,
    value: string|undefined,
    details?: RegisteredPropertyDetails,
  }) {
    super();
    this.variableName = variableName;
    this.details = details;
    this.value = value;
  }

  get value(): string|undefined {
    return this.#value;
  }

  set value(value: string|undefined) {
    this.#value = value;
    this.#render();
  }

  #render(): void {
    const initialValue = this.details?.registration.initialValue();
    const registrationView = this.details ? html`
        <hr class=divider />
        <div class=registered-property-popup-wrapper>
          <div class="monospace">
            <div><span class="css-property">syntax:</span> ${this.details.registration.syntax()}</div>
            <div><span class="css-property">inherits:</span> ${this.details.registration.inherits()}</div>
            ${initialValue ? html`<div><span class="css-property">initial-value:</span> ${initialValue}</div>` : ''}
          </div>
          ${getLinkSection(this.details)}
        </div>` :
                                            '';

    const valueText = this.value ?? i18nString(UIStrings.sIsNotDefined, {PH1: this.variableName});
    render(
        html`<style>${cssVariableValueViewStyles}</style>
             <div class="variable-value-popup-wrapper">
               ${valueText}
             </div>
             ${registrationView}
             `,
        this.#shadow, {
          host: this,
        });
  }
}

customElements.define('devtools-css-variable-value-view', CSSVariableValueView);
customElements.define('devtools-css-variable-parser-error', CSSVariableParserError);

declare global {
  interface HTMLElementTagNameMap {
    'devtools-css-variable-value-view': CSSVariableValueView;
    'devtools-css-variable-parser-error': CSSVariableParserError;
  }
}
