const JavaScriptRelation = require('../JavaScriptRelation');

class JavaScriptImportScripts extends JavaScriptRelation {
  static get selector() {
    return 'CallExpression:has(Identifier.callee[name=importScripts], MemberExpression.callee[computed=false]:has(Identifier.object[name=self]) > Identifier.property[name=importScripts])';
  }

  static handler(node, stack) {
    const parentNode = stack[0];
    const parentParentNode = stack[1];
    const outgoingRelations = [];
    for (const argumentNode of node.arguments) {
      if (
        argumentNode.type === 'Literal' &&
        typeof argumentNode.value === 'string'
      ) {
        outgoingRelations.push({
          type: 'JavaScriptImportScripts',
          detachableNode:
            parentNode.type === 'SequenceExpression' ? node : parentNode,
          parentNode:
            parentNode.type === 'SequenceExpression'
              ? parentNode
              : parentParentNode,
          argumentsNode: node.arguments,
          node: argumentNode,
          href: argumentNode.value,
        });
      }
    }
    return outgoingRelations;
  }

  get href() {
    return this.node.value;
  }

  set href(href) {
    this.node.value = href;
  }

  inline() {
    throw new Error('JavaScriptImportScripts.inline(): Not supported');
  }

  attach(position, adjacentRelation) {
    this.node = { type: 'Literal', value: '<urlGoesHere>' };
    if (position === 'before' || position === 'after') {
      this.detachableNode = adjacentRelation.detachableNode;
      this.argumentsNode = adjacentRelation.argumentsNode;
      this.parentNode = adjacentRelation.parentNode;
      const argumentsNodeIndex = this.argumentsNode.indexOf(
        adjacentRelation.node
      );
      if (argumentsNodeIndex === -1) {
        throw new Error(
          'JavaScriptImportScripts.attach: adjacentRelation.node not found in adjacentRelation.argumentsNode'
        );
      }
      this.argumentsNode.splice(
        argumentsNodeIndex + (position === 'after' ? 1 : 0),
        0,
        this.node
      );
    } else {
      this.parentNode = this.from.parseTree;
      this.detachableNode = {
        type: 'ExpressionStatement',
        expression: {
          type: 'CallExpression',
          callee: {
            type: 'Identifier',
            name: 'importScripts',
          },
          arguments: [this.node],
        },
      };
      if (position === 'first') {
        this.parentNode.body.unshift(this.detachableNode);
      } else if (position === 'last') {
        this.parentNode.body.push(this.detachableNode);
      } else {
        throw new Error(
          `JavaScriptImportScripts.attach: Unsupported 'position' value: ${position}`
        );
      }
    }
    return super.attach(position, adjacentRelation);
  }

  detach() {
    const i = this.argumentsNode.indexOf(this.node);
    if (i === -1) {
      throw new Error(
        'relations.JavaScriptWebWorker.detach: this.node not found in module array of this.arrayNode.'
      );
    }
    this.argumentsNode.splice(i, 1);
    if (this.argumentsNode.length === 0) {
      // Remove the importScripts() call instead of leaving it with no arguments
      if (this.parentNode.type === 'SequenceExpression') {
        this.parentNode.expressions.splice(
          this.parentNode.expressions.indexOf(this.detachableNode),
          1
        );
      } else {
        this.parentNode.body.splice(
          this.parentNode.body.indexOf(this.detachableNode),
          1
        );
      }
    }
    return super.detach();
  }
}

JavaScriptImportScripts.prototype.targetType = 'JavaScript';

module.exports = JavaScriptImportScripts;
