/**
 * Copyright (c) 2016-present, Nicolas Gallagher.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import modality from './modality';

export default class WebStyleSheet {
  _cssRules = [];
  _sheet = null;
  _textContent = '';

  constructor(id: string) {
    let domStyleElement;

    // on the client we check for an existing style sheet before injecting
    if (canUseDOM) {
      domStyleElement = document.getElementById(id);
      if (!domStyleElement) {
        const html = `<style id="${id}"></style>`;
        if (document.head) {
          document.head.insertAdjacentHTML('afterbegin', html);
          domStyleElement = document.getElementById(id);
        }
      }

      if (domStyleElement) {
        // $FlowFixMe
        this._sheet = domStyleElement.sheet;
        this._textContent = domStyleElement.textContent;
      }
    }

    modality((rule) => this.insertRuleOnce(rule, 0));
  }

  containsRule(rule: string): boolean {
    return this._cssRules.indexOf(rule) > -1;
  }

  get cssText(): string {
    return this._cssRules.join('\n');
  }

  insertRuleOnce(rule: string, position: ?number) {
    // Reduce chance of duplicate rules
    if (!this.containsRule(rule)) {
      if (position != null) {
        this._cssRules.splice(position, 0, rule);
      } else {
        this._cssRules.push(rule);
      }

      // Check whether a rule was part of any prerendered styles (textContent
      // doesn't include styles injected via 'insertRule')
      if (this._textContent.indexOf(rule) === -1 && this._sheet) {
        const pos = position || this._sheet.cssRules.length;
        try {
          this._sheet.insertRule(rule, pos);
        } catch (e) {
          if (process.env.NODE_ENV !== 'production') {
            console.warn(
              `Failed to inject CSS: "${rule}". The browser may have rejecting unrecognized vendor prefixes. (This should have no user-facing impact.)`
            );
          }
        }
      }
    }
  }
}
