var _a;
import { __decorate, __extends } from "tslib";
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop, Watch } from 'vue-property-decorator';
import { ElementQueries } from '../../mixins/element-queries/element-queries';
import { MediaQueries } from '../../mixins/media-queries/media-queries';
import uuid from '../../utils/uuid/uuid';
import { ModulVue } from '../../utils/vue/vue';
import { DYNAMIC_TEMPLATE_NAME, I18N_NAME, LIMIT_TEXT_NAME, LINK_NAME } from '../component-names';
import { MDynamicTemplate } from '../dynamic-template/dynamic-template';
import { MI18n } from '../i18n/i18n';
import { MLink, MLinkMode } from '../link/link';
import WithRender from './limit-text.html?style=./limit-text.scss';
var MLimitText = /** @class */ (function (_super) {
    __extends(MLimitText, _super);
    function MLimitText() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.reduceContent = '';
        _this.testingContent = '';
        _this.fullContent = '';
        _this.internalOpen = false;
        _this.hasFinish = false;
        _this.contentTooTall = false;
        _this.initLineHeigh = '';
        _this.maxHeight = 0;
        _this.uuid = uuid.generate();
        return _this;
    }
    MLimitText.prototype.mounted = function () {
        var _this = this;
        this.internalOpen = this.open;
        // ------------ Resize section ------------
        this.$nextTick(function () {
            _this.as().$on('resizeDone', _this.reset);
        });
        // ---------------------------------------
        // ------------ Watch slot content -------
        this.observer = new MutationObserver(function () {
            _this.reset();
        });
        this.observer.observe(this.$refs.originalText, { subtree: true, childList: true, characterData: true });
        // ---------------------------------------
        this.initialize();
    };
    MLimitText.prototype.destroyed = function () {
        if (this.child) {
            this.child.removeEventListener('click', this.openText);
            this.child.removeEventListener('click', this.closeText);
        }
        this.observer.disconnect();
    };
    MLimitText.prototype.initialize = function () {
        this.el = this.$refs.testingText;
        if (this.el) {
            this.el.innerHTML = this.$refs.originalText.innerHTML;
            this.testingContent = this.el.innerHTML;
            this.el.style.whiteSpace = 'nowrap';
            for (var i = 1; i < this.el.children.length; i++) {
                this.el.children[i].style.display = 'none';
            }
            this.initLineHeigh = this.el.clientHeight;
            for (var i = 1; i < this.el.children.length; i++) {
                this.el.children[i].style.display = 'block';
            }
            this.el.style.whiteSpace = 'normal';
            this.maxHeight = this.lines * this.initLineHeigh;
            // Generate the full content - Add the close link if an HTML tag is present
            if (this.testingContent.match('</')) {
                var tagIndex = this.testingContent.lastIndexOf('</');
                this.fullContent = this.testingContent.substring(0, tagIndex) + this.closeLink + this.testingContent.substring(tagIndex);
            }
            else {
                this.fullContent = this.testingContent + this.closeLink;
            }
            // Get the limited text
            this.adjustText();
        }
    };
    MLimitText.prototype.adjustText = function () {
        if (this.isContentTooTall(false)) {
            this.contentTooTall = true;
            this.hasFinish = false;
            this.getReduceContent();
            this.hasFinish = true;
        }
        else {
            this.contentTooTall = false;
            this.hasFinish = true;
        }
    };
    MLimitText.prototype.isContentTooTall = function (update) {
        if (update) {
            this.updateContent(this.reduceContent, this.el);
        }
        var currentHeight = (this.el).clientHeight;
        return (currentHeight > this.maxHeight);
    };
    MLimitText.prototype.updateContent = function (content, el) {
        el.innerHTML = content;
    };
    MLimitText.prototype.reset = function () {
        var _this = this;
        this.hasFinish = false;
        this.reduceContent = '';
        this.testingContent = '';
        this.$nextTick(function () {
            _this.initialize();
        });
    };
    MLimitText.prototype.getReduceContent = function () {
        var HTMLcontent = this.fullContent;
        var index = 0;
        var lastValidContent = '';
        var closingTag = '';
        while (index < HTMLcontent.length && !this.isContentTooTall(true)) {
            if (HTMLcontent[index] === '<' && (index + 1) < HTMLcontent.length) {
                switch (true) {
                    // Opening tag
                    case /\w/.test(HTMLcontent[index + 1]):
                        var tag = '</';
                        index++;
                        var endTagName = false;
                        while (HTMLcontent[index] !== '>') {
                            if (!endTagName && /\w/.test(HTMLcontent[index])) {
                                tag += HTMLcontent[index];
                            }
                            else {
                                endTagName = true;
                            }
                            index++;
                        }
                        tag += '>';
                        // Do not keep the tag if it is a "self closing" tag
                        if (!/<\/(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)>$/.test(tag)) {
                            closingTag = tag + closingTag;
                        }
                        break;
                    // Closing tag
                    case (HTMLcontent[index + 1] === '/'):
                        var endTag = '</';
                        index += 2;
                        while (HTMLcontent[index] !== '>') {
                            endTag += HTMLcontent[index];
                            index++;
                        }
                        endTag += '>';
                        closingTag = closingTag.slice(endTag.length);
                        break;
                }
            }
            lastValidContent = this.reduceContent;
            this.reduceContent = HTMLcontent.substring(0, index + 1) + this.openLinkOriginal + closingTag;
            index++;
        }
        this.reduceContent = lastValidContent.replace(this.openLinkOriginal, this.openLink);
    };
    Object.defineProperty(MLimitText.prototype, "getReduceText", {
        get: function () {
            return this.reduceContent;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "getFullText", {
        get: function () {
            return this.fullContent;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "openLinkOriginal", {
        get: function () {
            return '...&nbsp' + new this.openLinkOriginalRendered().$mount().$el.outerHTML;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "openLinkOriginalRendered", {
        get: function () {
            var vNodeData = {
                props: {
                    mode: MLinkMode.Button,
                    underline: false
                },
                attrs: {
                    style: 'font-weight:400;',
                    title: this.getOpenLabelTitle,
                    'data-id': this.uuid
                }
            };
            var vNodeChildren = '[' + (this.openLabel ? this.openLabel.replace(/\s/g, '\xa0') : '\xa0+\xa0') + ']';
            return Vue.extend({
                render: function (createElement) {
                    return createElement(LINK_NAME, vNodeData, vNodeChildren);
                }
            });
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "openLink", {
        get: function () {
            return '...&nbsp' + new this.openLinkRendered().$mount().$el.outerHTML;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "openLinkRendered", {
        get: function () {
            var vNodeData = {
                props: {
                    mode: MLinkMode.Button,
                    underline: false
                },
                attrs: {
                    title: this.getOpenLabelTitle,
                    'data-id': this.uuid
                }
            };
            var vNodeChildren = '[' + (this.openLabel ? this.openLabel.replace(/\s/g, '\xa0') : '\xa0+\xa0') + ']';
            return Vue.extend({
                render: function (createElement) {
                    return createElement(LINK_NAME, vNodeData, vNodeChildren);
                }
            });
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "closeLink", {
        get: function () {
            return '&nbsp;' + new this.closeLinkRendered().$mount().$el.outerHTML;
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "closeLinkRendered", {
        get: function () {
            var vNodeData = {
                props: {
                    mode: MLinkMode.Button,
                    underline: false
                },
                attrs: {
                    title: this.getCloseLabelTitle,
                    'data-id': this.uuid
                }
            };
            var vNodeChildren = '[' + (this.closeLabel ? this.closeLabel.replace(/\s/g, '\xa0') : '\xa0-\xa0') + ']';
            return Vue.extend({
                render: function (createElement) {
                    return createElement(LINK_NAME, vNodeData, vNodeChildren);
                }
            });
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "getOpenLabelTitle", {
        get: function () {
            return this.openLabel ? this.openLabel.replace(/\s/g, '\xa0') : this.$i18n.translate('m-limit-text:open');
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MLimitText.prototype, "getCloseLabelTitle", {
        get: function () {
            return this.closeLabel ? this.closeLabel.replace(/\s/g, '\xa0') : this.$i18n.translate('m-limit-text:close');
        },
        enumerable: false,
        configurable: true
    });
    MLimitText.prototype.openChanged = function (open) {
        this.internalOpen = open;
    };
    MLimitText.prototype.openText = function (event) {
        this.internalOpen = true;
        this.$emit('open');
        event.preventDefault();
    };
    MLimitText.prototype.closeText = function (event) {
        this.internalOpen = false;
        this.$emit('close');
        event.preventDefault();
    };
    MLimitText.prototype.onUpdatedOpen = function (component) {
        var link = component[0].$el.querySelector('a[data-id="' + this.uuid + '"]');
        if (this.child) {
            this.child.removeEventListener('click', this.openText);
        }
        if (link) {
            this.child = link;
            this.child.addEventListener('click', this.openText);
        }
    };
    MLimitText.prototype.onUpdatedClose = function (component) {
        var link = component[0].$el.querySelector('a[data-id="' + this.uuid + '"]');
        if (this.child) {
            this.child.removeEventListener('click', this.closeText);
        }
        if (link) {
            this.child = link;
            this.child.addEventListener('click', this.closeText);
        }
    };
    __decorate([
        Prop()
    ], MLimitText.prototype, "open", void 0);
    __decorate([
        Prop({ default: 4 })
    ], MLimitText.prototype, "lines", void 0);
    __decorate([
        Prop()
    ], MLimitText.prototype, "openLabel", void 0);
    __decorate([
        Prop()
    ], MLimitText.prototype, "closeLabel", void 0);
    __decorate([
        Prop()
    ], MLimitText.prototype, "html", void 0);
    __decorate([
        Watch('open')
    ], MLimitText.prototype, "openChanged", null);
    MLimitText = __decorate([
        WithRender,
        Component({
            components: (_a = {},
                _a[I18N_NAME] = MI18n,
                _a[LINK_NAME] = MLink,
                _a[DYNAMIC_TEMPLATE_NAME] = MDynamicTemplate,
                _a),
            mixins: [MediaQueries, ElementQueries]
        })
    ], MLimitText);
    return MLimitText;
}(ModulVue));
export { MLimitText };
var LimitTextPlugin = {
    install: function (v, options) {
        v.component(LIMIT_TEXT_NAME, MLimitText);
    }
};
export default LimitTextPlugin;
//# sourceMappingURL=limit-text.js.map