import type { NodePath } from "@babel/traverse";
import * as t from "@babel/types";

export default function bindifyDecorators(
  decorators: Array<NodePath>,
): Array<NodePath> {
  for (const decoratorPath of decorators) {
    const decorator = decoratorPath.node;
    const expression = decorator.expression;
    if (!t.isMemberExpression(expression)) continue;

    const temp = decoratorPath.scope.maybeGenerateMemoised(expression.object);
    let ref;

    const nodes = [];

    if (temp) {
      ref = temp;
      nodes.push(t.assignmentExpression("=", temp, expression.object));
    } else {
      ref = expression.object;
    }

    nodes.push(
      t.callExpression(
        t.memberExpression(
          t.memberExpression(ref, expression.property, expression.computed),
          t.identifier("bind"),
        ),
        [ref],
      ),
    );

    if (nodes.length === 1) {
      decorator.expression = nodes[0];
    } else {
      decorator.expression = t.sequenceExpression(nodes);
    }
  }
}
