import { BaseNode } from './BaseNode.js';

/**
 * AST node for predicate calls
 * Represents: hasRole(user, role), owns(user, doc)
 */
export class PredicateNode extends BaseNode {
  constructor(name, location = null) {
    super('Predicate', location);
    this.name = name;
    this.arguments = [];
  }

  /**
   * Add an argument to this predicate
   * @param {ExpressionNode} argument - Argument to add
   */
  addArgument(argument) {
    this.arguments.push(argument);
    this.addChild(argument);
  }

  /**
   * Get the predicate name
   * @returns {string} Predicate name
   */
  getName() {
    return this.name;
  }

  /**
   * Get all arguments
   * @returns {ExpressionNode[]} Predicate arguments
   */
  getArguments() {
    return this.arguments;
  }

  /**
   * Get the number of arguments
   * @returns {number} Number of arguments
   */
  getArgumentCount() {
    return this.arguments.length;
  }

  /**
   * Get an argument by index
   * @param {number} index - Argument index
   * @returns {ExpressionNode|null} Argument or null
   */
  getArgument(index) {
    return this.arguments[index] || null;
  }

  /**
   * Check if this predicate has a specific number of arguments
   * @param {number} count - Expected argument count
   * @returns {boolean} True if has expected count
   */
  hasArgumentCount(count) {
    return this.arguments.length === count;
  }

  /**
   * Check if this predicate has any arguments
   * @returns {boolean} True if has arguments
   */
  hasArguments() {
    return this.arguments.length > 0;
  }

  /**
   * Get the signature string for this predicate
   * @returns {string} Predicate signature
   */
  getSignature() {
    const argStr = this.arguments.map(arg => arg.toString()).join(', ');
    return `${this.name}(${argStr})`;
  }

  /**
   * Validate the predicate
   * @returns {string[]} Array of error messages
   */
  validate() {
    const errors = [];

    // Validate predicate name
    if (!this.name || typeof this.name !== 'string') {
      errors.push(`Invalid predicate name: ${this.name}`);
    }

    // Validate arguments
    this.arguments.forEach((arg, index) => {
      const argErrors = arg.validate ? arg.validate() : [];
      errors.push(...argErrors.map(err => `Argument ${index + 1}: ${err}`));
    });

    return errors;
  }

  toString() {
    return `Predicate(${this.getSignature()})`;
  }
}
