/**
 * Copyright 2026 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {LitElement, css, html} from 'lit';
import {SHARED_STYLES} from '../css/shared-css.js';
import {customElement, property, state} from 'lit/decorators.js';

@customElement('chromedash-callout')
class ChromedashCallout extends LitElement {
  @property({type: String})
  targetId = '';
  /** TODO(jrobbins) Support sides other than "south". */
  @property({type: String})
  side: 'north' | 'south' | 'east' | 'west' = 'south';
  /** String to send to the server when dismissed. */
  @property({type: String})
  cue = '';
  @property({attribute: false, type: Array})
  dismissedCues: string[] = [];
  @property({type: Boolean})
  signedIn = false;
  @property({type: Boolean})
  hidden = true;
  @state()
  top = 0;
  @state()
  left = 0;

  connectedCallback() {
    super.connectedCallback();
    if (this.dismissedCues.includes(this.cue)) {
      // Don't show the cue because the user has already dismissed it.
      return;
    }
    try {
      this.attachToTarget(this.parentNode!.querySelector('#' + this.targetId));
    } catch (error) {
      console.error('Failed to attach target', error);
    }
  }

  static get styles() {
    return [
      ...SHARED_STYLES,
      css`
        #bubble {
          position: absolute;
          display: inline-block;
          background: var(--callout-bg-color);
          border-radius: var(--large-border-radius);
          padding: var(--content-padding-half);
          max-width: 24em;
          color: var(--callout-text-color);
          font-weight: bold;
        }
        #bubble[hidden] {
          display: none;
        }
        #bubble:after {
          content: '';
          position: absolute;
          border: 20px solid transparent;
        }
        /* Bubble will be located on the south side of target element. */
        #bubble.south:after {
          top: -20px;
          left: 20px;
          width: 0;
          height: 0;
          border-bottom-color: var(--callout-bg-color);
          border-top: 0;
        }
        #closebox {
          float: right;
          margin-left: var(--content-padding-half);
          color: var(--light-icon-fill-color);
        }
        #cue-content-container {
          margin: var(--content-padding-quarter);
        }
      `,
    ];
  }

  // TODO(jrobbins): Consider using:
  // el.getBoundingClientRect().top + window.scrollY
  // and creating the bubble directly under the document.
  contentOffsetTop(el) {
    let offset = 0;
    while (el.offsetParent && el != this.offsetParent) {
      offset += el.offsetTop;
      el = el.offsetParent;
    }
    return offset;
  }

  contentOffsetLeft(el) {
    let offset = 0;
    while (el.offsetParent && el != this.offsetParent) {
      offset += el.offsetLeft;
      el = el.offsetParent;
    }
    return offset;
  }

  attachToTarget(el) {
    if (this.side == 'south') {
      const targetBottom = this.contentOffsetTop(el) + el.offsetHeight;
      this.top = targetBottom + 20;
      this.left = Math.max(this.contentOffsetLeft(el) - 20, 0);
    }
    /* TODO(jrobbins): Implement support for other sides. */
    this.hidden = false;
  }

  dismiss() {
    this.hidden = true;
    if (this.signedIn) {
      window.csClient.dismissCue(this.cue);
    }
    // Signed out users simply hide this element without storing
    // the fact that the cue was dismissed.
  }

  render() {
    return html`
      <div
        id="bubble"
        class="${this.side}"
        ?hidden=${this.hidden}
        style="top:${this.top}px; left:${this.left}px;"
      >
        <sl-icon id="closebox" name="x" @click=${this.dismiss}></sl-icon>
        <div id="cue-content-container">
          <slot></slot>
        </div>
      </div>
    `;
  }
}
