"use strict";
const HTMLElementImpl = require("./HTMLElement-impl").implementation;
const { addStyleSheet, removeStyleSheet, createStyleSheetForElement } = require("../css/helpers/stylesheets");
const { childTextContent } = require("../helpers/text");
const { asciiCaseInsensitiveMatch } = require("../helpers/strings");

class HTMLStyleElementImpl extends HTMLElementImpl {
  constructor(globalObject, args, privateData) {
    super(globalObject, args, privateData);

    this.sheet = null;
    this._isOnStackOfOpenElements = false;
  }

  get disabled() {
    return this.sheet?.disabled ?? false;
  }

  set disabled(value) {
    if (this.sheet) {
      this.sheet.disabled = value;
    }
  }

  _attach() {
    super._attach();
    if (!this._isOnStackOfOpenElements) {
      this._updateAStyleBlock();
    }
  }

  _detach() {
    super._detach();
    if (!this._isOnStackOfOpenElements) {
      this._updateAStyleBlock();
    }
  }

  _childTextContentChangeSteps() {
    super._childTextContentChangeSteps();

    // This guard is not required by the spec, but should be unobservable (since you can't run script during the middle
    // of parsing a <style> element) and saves a bunch of unnecessary work.
    if (!this._isOnStackOfOpenElements) {
      this._updateAStyleBlock();
    }
  }

  _poppedOffStackOfOpenElements() {
    this._isOnStackOfOpenElements = false;
    this._updateAStyleBlock();
  }

  _pushedOnStackOfOpenElements() {
    this._isOnStackOfOpenElements = true;
  }

  _updateAStyleBlock() {
    if (this.sheet) {
      removeStyleSheet(this.sheet, this);
    }

    // Browsing-context connected, per https://github.com/whatwg/html/issues/4547
    if (!this.isConnected || !this._ownerDocument._defaultView) {
      return;
    }

    const type = this.getAttributeNS(null, "type");
    if (type !== null && type !== "" && !asciiCaseInsensitiveMatch(type, "text/css")) {
      return;
    }

    // Not implemented: CSP

    const content = childTextContent(this);
    const createdSheet = createStyleSheetForElement(content, this);
    addStyleSheet(createdSheet, this);
  }
}

module.exports = {
  implementation: HTMLStyleElementImpl
};
