// @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';
// Utilities
import { getIndexes, extractClassName, getClassByType, checkIsColorLight, lightenOrDarken, } from './utilities/utilities';
// Default values
import { DEFAULT_PARENT_STYLE } from './constants/defaultValues';
// Components
import './components/placeholder';
import './components/knobs/textarea';
import { close } from './components/icons/icons';
import hljs from 'highlight.js/lib/core';
export class AnnotativeBaseComponent extends LitElement {
    constructor() {
        super();
        this.annotativeInnerRef = createRef();
        this.parentStyle = DEFAULT_PARENT_STYLE;
        this._showPopup = false;
        this._copyValue = '';
        this.contentsWithPlaceholders = [];
        this.content = '';
        this.placeholder = {};
        this.themeCss = '';
        this.placeholderMask = '{{{{____placeholder____}}}}';
        this.encloser = '____';
        this.styleMap = {};
        this._computeNewValueObj = (updatedKey, newValue) => {
            const valueObj = Object.entries(this.placeholder).reduce((acc, cur) => {
                const [placeholderMask, placeholderConfig] = cur;
                return {
                    ...acc,
                    [placeholderMask]: placeholderMask === updatedKey ? newValue : placeholderConfig.value,
                };
            }, {});
            return valueObj;
        };
        this._onChange = (updatedKey, event) => {
            const target = event.target;
            const config = this.placeholder[updatedKey];
            const newValue = config.type === 'boolean'
                ? target.checked
                : config.type === 'number'
                    ? parseFloat(target.value)
                    : config.type === 'integer'
                        ? parseInt(target.value)
                        : target.value;
            const valueObj = this._computeNewValueObj(updatedKey, newValue);
            this.placeholder = {
                ...this.placeholder,
                [updatedKey]: {
                    ...this.placeholder[updatedKey],
                    value: newValue,
                },
            };
            const detail = {
                updatedKey,
                valueObj,
            };
            if (this.handleChange) {
                this.handleChange(detail);
            }
            else {
                this.dispatchEvent(new CustomEvent('change', {
                    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 placeholder = `${this.encloser}${key}${this.encloser}`;
                    return prev.replaceAll(placeholder, 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('contentsWithPlaceholders');
        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);
    }
    _insertPlaceholderKeysAndGetKeyIndexes(placeholder = {}) {
        const placeholderKeys = Object.keys(placeholder);
        // 1. Insert placeholders to content and get key indexes
        let contentWithPlaceholders = this.content;
        let keyIndexes = [];
        for (let i = 0; i < placeholderKeys.length; i++) {
            const placeholderKey = placeholderKeys[i];
            const placeholderKeyWithEncloser = `${this.encloser}${placeholderKey}${this.encloser}`;
            const indexes = getIndexes(this.content, placeholderKeyWithEncloser);
            keyIndexes = [
                ...keyIndexes,
                ...indexes.map((index) => ({ placeholderKey, index })),
            ];
            contentWithPlaceholders = contentWithPlaceholders.replaceAll(placeholderKeyWithEncloser, this.placeholderMask);
        }
        // 2. Sort for later knobs insertion
        keyIndexes = keyIndexes.sort((a, b) => {
            return a.index - b.index;
        });
        return { contentWithPlaceholders, keyIndexes };
    }
    _highlight(contentWithPlaceholders) {
        return hljs.highlight(contentWithPlaceholders, {
            language: 'language',
        }).value;
    }
    _createContentsWithPlaceholders() {
        const placeholder = this.placeholder || {};
        // 1. and 2.
        let { contentWithPlaceholders, keyIndexes } = this._insertPlaceholderKeysAndGetKeyIndexes(placeholder);
        // 3. `Highlight` the content
        let contentsWithPlaceholders = [];
        let contentHighlighted = this._highlight(contentWithPlaceholders);
        let contentChunks = contentHighlighted.split(this.placeholderMask);
        // 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];
            contentsWithPlaceholders.push((i !== 0 ? `<span class=\"${classes[i - 1]}\">` : '') +
                contentChunk +
                '</span>');
            if (i !== contentChunks.length - 1) {
                const { placeholderKey: key, index } = keyIndexes[i];
                contentsWithPlaceholders.push({
                    key,
                    config: placeholder[key],
                });
            }
        }
        return contentsWithPlaceholders;
    }
    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">
        <style>
          ${this.themeCss}
        </style>
        <div
          id="annotative-inner"
          ${ref(this.annotativeInnerRef)}
          class="hljs"
          style="${styleMap(this.styleMap)}"
          @click=${() => (this._showPopup = false)}
        >${this.contentsWithPlaceholders?.map((content) => {
            const { key, config } = content;
            // 1. placeholder
            if (key) {
                return html `<span
                class="hljs-${getClassByType(config.type)} annotation-placeholder-container"
              >
                <annotative-placeholder
                  .key="${key}"
                  .config="${config}"
                  .isBgLight=${isBgLight}
                  .popupStyle=${popupStyle}
                  .onChange="${this._onChange}"
                ></annotative-placeholder>
              </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-knob-textarea
                .popupStyle=${popupStyle}
                .value=${this._copyValue}
              />
            </div>
          </div>
          <div class="close" @click=${this._onTriggerCopyPopup}>${close}</div>
        </div>
      </div>
    `;
    }
}
AnnotativeBaseComponent.styles = [
    css `
      #annotative {
        position: relative;
        font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
          Liberation Mono, Courier New, monospace;
      }
      #annotative-inner {
        position: relative;
        white-space: pre;
        text-wrap: wrap;
        line-height: 1.25;
      }
      .annotation-placeholder-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, "contentsWithPlaceholders", void 0);
__decorate([
    property({ attribute: 'languageFn' })
], AnnotativeBaseComponent.prototype, "languageFn", void 0);
__decorate([
    property({ attribute: 'content' })
], AnnotativeBaseComponent.prototype, "content", void 0);
__decorate([
    property({ attribute: 'placeholder' })
], AnnotativeBaseComponent.prototype, "placeholder", void 0);
__decorate([
    property({ attribute: 'themeCss' })
], AnnotativeBaseComponent.prototype, "themeCss", void 0);
__decorate([
    property({ attribute: 'placeholderMask' })
], AnnotativeBaseComponent.prototype, "placeholderMask", void 0);
__decorate([
    property({ attribute: 'encloser' })
], AnnotativeBaseComponent.prototype, "encloser", void 0);
__decorate([
    property({ attribute: 'styleMap' })
], AnnotativeBaseComponent.prototype, "styleMap", void 0);
__decorate([
    property({ attribute: 'handleChange' })
], AnnotativeBaseComponent.prototype, "handleChange", void 0);
//# sourceMappingURL=annotative-base-component.js.map