text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  const errors = require("../../../errors");
  const manipulation_1 = require("../../../manipulation");
  const structurePrinters_1 = require("../../../structurePrinters");
  const typescript_1 = require("../../../typescript");
  const callBaseSet_1 = require("../callBaseSet");
  const callBaseGetStructure_1 = require("../callBaseGetStructure");
  function ExtendsClauseableNode(Base) {
      return class extends Base {
          getExtends() {
              const extendsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ExtendsKeyword);
              return extendsClause == null ? [] : extendsClause.getTypeNodes();
          }
          addExtends(text) {
              return this.insertExtends(this.getExtends().length, text);
          }
          insertExtends(index, texts) {
              const originalExtends = this.getExtends();
              const wasStringInput = typeof texts === "string";
              if (typeof texts === "string") {
                  errors.throwIfWhitespaceOrNotString(texts, "texts");
                  texts = [texts];
              }
              else if (texts.length === 0) {
                  return [];
              }
              const writer = this._getWriterWithQueuedChildIndentation();
              const structurePrinter = new structurePrinters_1.CommaSeparatedStructuresPrinter(new structurePrinters_1.StringStructurePrinter());
              structurePrinter.printText(writer, texts);
              index = manipulation_1.verifyAndGetIndex(index, originalExtends.length);
              if (originalExtends.length > 0) {
                  const extendsClause = this.getHeritageClauseByKindOrThrow(typescript_1.SyntaxKind.ExtendsKeyword);
                  manipulation_1.insertIntoCommaSeparatedNodes({
                      parent: extendsClause.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.SyntaxList),
                      currentNodes: originalExtends,
                      insertIndex: index,
                      newText: writer.toString()
                  });
              }
              else {
                  const openBraceToken = this.getFirstChildByKindOrThrow(typescript_1.SyntaxKind.OpenBraceToken);
                  const openBraceStart = openBraceToken.getStart();
                  const isLastSpace = /\s/.test(this.getSourceFile().getFullText()[openBraceStart - 1]);
                  let insertText = `extends ${writer.toString()} `;
                  if (!isLastSpace)
                      insertText = " " + insertText;
                  manipulation_1.insertIntoParentTextRange({
                      parent: this,
                      insertPos: openBraceStart,
                      newText: insertText
                  });
              }
              const newExtends = this.getExtends();
              return wasStringInput ? newExtends[index] : manipulation_1.getNodesToReturn(originalExtends, newExtends, index, false);
          }
          removeExtends(implementsNodeOrIndex) {
              const extendsClause = this.getHeritageClauseByKind(typescript_1.SyntaxKind.ExtendsKeyword);
              if (extendsClause == null)
                  throw new errors.InvalidOperationError("Cannot remove an extends when none exist.");
              extendsClause.removeExpression(implementsNodeOrIndex);
              return this;
          }
          set(structure) {
              callBaseSet_1.callBaseSet(Base.prototype, this, structure);
              if (structure.extends != null) {
                  this.getExtends().forEach(e => this.removeExtends(e));
                  this.addExtends(structure.extends);
              }
              return this;
          }
          getStructure() {
              return callBaseGetStructure_1.callBaseGetStructure(Base.prototype, this, {
                  extends: this.getExtends().map(e => e.getText())
              });
          }
      };
  }
  exports.ExtendsClauseableNode = ExtendsClauseableNode;
  