// @ts-nocheck
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
// Lit
import { LitElement, html, css } from 'lit';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { property, state } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { ref, createRef } from 'lit/directives/ref.js';
import hljs from 'highlight.js/lib/core';
// Utilities
import { getIndexes, extractClassName, getClassByType, checkIsColorLight, lightenOrDarken, } from './utilities/utilities.js';
// Default values
import { DEFAULT_PARENT_STYLE } from './constants/defaultValues.js';
// Components
import './components/annotation.js';
import './components/knobs/textarea.js';
import { close } from './components/icons/icons.js';
export class AnnotativeBaseComponent extends LitElement {
    constructor() {
        super();
        this.annotativeInnerRef = createRef();
        this.parentStyle = DEFAULT_PARENT_STYLE;
        this._showPopup = false;
        this._copyValue = '';
        this.contentsWithAnnotations = [];
        this.content = '';
        this.annotation = {};
        this.themeCss = '';
        this.annotationMask = '{{{{____annotation____}}}}';
        this.encloser = '____';
        this.styleMap = {};
        this._computeNewValueObj = (updatedKey, newValue) => {
            const valueObj = Object.entries(this.annotation).reduce((acc, cur) => {
                const [annotationMask, annotationConfig] = cur;
                return {
                    ...acc,
                    [annotationMask]: annotationMask === updatedKey ? newValue : annotationConfig.value,
                };
            }, {});
            return valueObj;
        };
        this._onChange = (updatedKey, event) => {
            const target = event.target;
            const config = this.annotation[updatedKey];
            const newValue = config.type === 'boolean'
                ? target.checked
                : config.type === 'number'
                    ? parseFloat(target.value?.replace(/[^\d.-]/g, ''))
                    : config.type === 'integer'
                        ? parseInt(target.value?.replace(/[^\d.-]/g, ''))
                        : target.value;
            const valueObj = this._computeNewValueObj(updatedKey, newValue);
            this.annotation = {
                ...this.annotation,
                [updatedKey]: {
                    ...this.annotation[updatedKey],
                    value: newValue,
                },
            };
            const detail = {
                updatedKey,
                valueObj,
            };
            if (this.onValueChange) {
                this.onValueChange({ detail });
            }
            else {
                this.dispatchEvent(new CustomEvent('valuechange', {
                    detail,
                    bubbles: true,
                    composed: true,
                }));
            }
        };
        this._onTriggerCopyPopup = (e) => {
            e.stopPropagation();
            if (!this._showPopup) {
                const valueObj = this._computeNewValueObj();
                const copyValue = Object.entries(valueObj).reduce((prev, acc) => {
                    const [key, value] = acc;
                    const annotationWithEncloser = `${this.encloser}${key}${this.encloser}`;
                    return prev.replaceAll(annotationWithEncloser, value);
                }, this.content);
                this._copyValue = copyValue;
                window.navigator.clipboard.writeText(copyValue);
            }
            this._showPopup = !this._showPopup;
        };
    }
    async _loadAndHighlightSyntax() { }
    async _loadCss() {
        this.parentStyle = this._getComputedStyle(this.annotativeInnerRef);
        this.requestUpdate();
    }
    updated(changedProperties) {
        const cp = new Map(changedProperties);
        cp.delete('contentsWithAnnotations');
        cp.delete('themeCss');
        cp.delete('parentStyle');
        if (cp.size > 0) {
            this._loadAndHighlightSyntax();
        }
        if (changedProperties.has('themeCss')) {
            this._loadCss();
        }
    }
    _getComputedStyle(ref) {
        const style = (window && ref?.value ? window.getComputedStyle(ref.value) : {});
        const backgroundColor = style.backgroundColor || '';
        return { backgroundColor };
    }
    connectedCallback() {
        super.connectedCallback();
        this._handleResize = () => {
            const style = this._getComputedStyle(this.annotativeInnerRef);
            this.parentStyle = style;
        };
        window.addEventListener('resize', this._handleResize);
        setTimeout(this._handleResize, 1);
    }
    disconnectedCallback() {
        super.disconnectedCallback();
        window.removeEventListener('resize', this._handleResize);
    }
    _insertAnnotationKeysAndGetKeyIndexes(annotation = {}) {
        const annotationKeys = Object.keys(annotation);
        // 1. Insert annotations to content and get key indexes
        let contentWithAnnotations = this.content;
        let keyIndexes = [];
        for (let i = 0; i < annotationKeys.length; i++) {
            const annotationKey = annotationKeys[i];
            const annotationKeyWithEncloser = `${this.encloser}${annotationKey}${this.encloser}`;
            const indexes = getIndexes(this.content, annotationKeyWithEncloser);
            keyIndexes = [
                ...keyIndexes,
                ...indexes.map((index) => ({ annotationKey, index })),
            ];
            contentWithAnnotations = contentWithAnnotations.replaceAll(annotationKeyWithEncloser, this.annotationMask);
        }
        // 2. Sort for later knobs insertion
        keyIndexes = keyIndexes.sort((a, b) => {
            return a.index - b.index;
        });
        return { contentWithAnnotations, keyIndexes };
    }
    _highlight(contentWithAnnotations) {
        return hljs.highlight(contentWithAnnotations, {
            language: 'language',
        }).value;
    }
    _createContentsWithAnnotations() {
        const annotation = this.annotation || {};
        // 1. and 2.
        let { contentWithAnnotations, keyIndexes } = this._insertAnnotationKeysAndGetKeyIndexes(annotation);
        // 3. `Highlight` the content
        let contentsWithAnnotation = [];
        let contentHighlighted = this._highlight(contentWithAnnotations);
        let contentChunks = contentHighlighted.split(this.annotationMask);
        // 4. Extract last occurence
        let classes = contentChunks.map((chunk) => {
            return extractClassName(chunk, 'class="', '">');
        });
        classes.pop();
        // 5. Knobs insertion
        for (let i = 0; i < contentChunks.length; i++) {
            const contentChunk = contentChunks[i];
            contentsWithAnnotation.push((i !== 0 ? `<span class=\"${classes[i - 1]}\">` : '') +
                contentChunk +
                '</span>');
            if (i !== contentChunks.length - 1) {
                const { annotationKey: key, index } = keyIndexes[i];
                contentsWithAnnotation.push({
                    key,
                    config: annotation[key],
                });
            }
        }
        return contentsWithAnnotation;
    }
    render() {
        //
        const style = this.parentStyle;
        const isBgLight = checkIsColorLight(style.backgroundColor);
        const textColor = isBgLight ? 'rgb(237, 237, 237)' : 'rgb(18, 18, 18)';
        const inputBorderColor = lightenOrDarken(textColor);
        const popupStyle = {
            backgroundColor: lightenOrDarken(style.backgroundColor, 8),
            borderColor: lightenOrDarken(style.backgroundColor, 8 + 16),
            textColor,
            inputBorderColor,
        };
        const sharePopupStyle = {
            backgroundColor: popupStyle.backgroundColor,
            borderColor: popupStyle.borderColor,
            color: popupStyle.textColor,
        };
        return html `
      <div id="annotative-code">
        <style>
          ${this.themeCss}
        </style>
        <div
          id="annotative-code-inner"
          ${ref(this.annotativeInnerRef)}
          class="hljs"
          style="${styleMap(this.styleMap ?? {})}"
          @click=${() => (this._showPopup = false)}
        >${this.contentsWithAnnotations?.map((content) => {
            const { key, config } = content;
            // 1. annotation
            if (key) {
                return html `<span
                class="hljs-${getClassByType(config.type)} annotative-code-annotation-container"
              >
                <annotative-code-annotation
                  .key="${key}"
                  .config="${config}"
                  .isBgLight=${isBgLight}
                  .popupStyle=${popupStyle}
                  .onChange="${this._onChange}"
                />
              </span>`;
            }
            // 2. highlighted content
            return unsafeHTML(content);
        })}</div>
        <div
          id="copy-button"
          style="${styleMap({
            backgroundColor: popupStyle.borderColor,
            color: popupStyle.textColor,
        })}"
          @click=${this._onTriggerCopyPopup}
        >
          Copy
        </div>
        <div
          id="copy-popup"
          class="${this._showPopup ? 'show' : ''}"
          style="${styleMap(sharePopupStyle)}"
        >
          <div class="inner">
            <div class="copy">Copied</div>
            <div>
              <annotative-code-knob-textarea
                .popupStyle=${popupStyle}
                .value=${this._copyValue}
              />
            </div>
          </div>
          <div class="close" @click=${this._onTriggerCopyPopup}>${close}</div>
        </div>
      </div>
    `;
    }
}
AnnotativeBaseComponent.styles = [
    css `
      #annotative-code {
        position: relative;
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
          Liberation Mono, Courier New, monospace;
      }
      #annotative-code-inner {
        position: relative;
        white-space: pre;
        text-wrap: wrap;
        line-height: 1.25;
      }
      .annotative-code-annotation-container {
        display: inline-block;
        white-space: initial;
      }

      #copy-button {
        position: absolute;
        top: 0;
        right: 0;
        padding: 4px 6px;
        cursor: pointer;
      }

      #copy-popup {
        position: absolute;
        top: 32px;
        right: 6px;
        width: 0;
        border-radius: 12px;
        overflow: hidden;
      }

      #copy-popup.show {
        width: 240px;
        padding: 4px;
      }

      #copy-popup .inner {
        padding: 6px;
      }

      #copy-popup .inner .copy {
        padding-bottom: 6px;
        border-bottom: 1px solid;
      }

      #copy-popup .inner .icons div {
        padding: 6px;
        border: 1px solid;
        width: 24px;
        height: 24px;
      }

      #copy-popup .close {
        position: absolute;
        top: 6px;
        right: 6px;
        width: 24px;
        height: 24px;
        cursor: pointer;
      }
    `,
];
__decorate([
    property()
], AnnotativeBaseComponent.prototype, "parentStyle", void 0);
__decorate([
    state()
], AnnotativeBaseComponent.prototype, "_showPopup", void 0);
__decorate([
    state()
], AnnotativeBaseComponent.prototype, "_copyValue", void 0);
__decorate([
    state()
], AnnotativeBaseComponent.prototype, "hljs", void 0);
__decorate([
    state()
], AnnotativeBaseComponent.prototype, "contentsWithAnnotations", void 0);
__decorate([
    property({ attribute: false })
], AnnotativeBaseComponent.prototype, "languageFn", void 0);
__decorate([
    property({ attribute: 'content' })
], AnnotativeBaseComponent.prototype, "content", void 0);
__decorate([
    property({ attribute: false })
], AnnotativeBaseComponent.prototype, "annotation", void 0);
__decorate([
    property({ attribute: 'themeCss' })
], AnnotativeBaseComponent.prototype, "themeCss", void 0);
__decorate([
    property({ attribute: 'annotationMask' })
], AnnotativeBaseComponent.prototype, "annotationMask", void 0);
__decorate([
    property({ attribute: 'encloser' })
], AnnotativeBaseComponent.prototype, "encloser", void 0);
__decorate([
    property({ attribute: false })
], AnnotativeBaseComponent.prototype, "styleMap", void 0);
__decorate([
    property({ attribute: false })
], AnnotativeBaseComponent.prototype, "onValueChange", void 0);
//# sourceMappingURL=annotative-base-component.js.map