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

/**
 * AST node for defeasible logic statements
 * Represents: ALWAYS, WHEN, UNLESS, REQUIRES statements
 */
export class DefeasibleLogicNode extends BaseNode {
  constructor(logicType, location = null) {
    super('DefeasibleLogic', location);
    this.logicType = logicType; // 'ALWAYS', 'WHEN', 'UNLESS', 'REQUIRES'
    this.condition = null; // ExpressionNode or EvidenceBodyNode
    this.defeater = null; // ExpressionNode or EvidenceBodyNode (for WHEN/UNLESS)
  }

  /**
   * Set the condition for this defeasible logic
   * @param {BaseNode} condition - Condition to set
   */
  setCondition(condition) {
    this.condition = condition;
    this.addChild(condition);
  }

  /**
   * Set the defeater for this defeasible logic (for WHEN/UNLESS)
   * @param {BaseNode} defeater - Defeater to set
   */
  setDefeater(defeater) {
    this.defeater = defeater;
    this.addChild(defeater);
  }

  /**
   * Check if this is an ALWAYS statement
   * @returns {boolean} True if ALWAYS
   */
  isAlways() {
    return this.logicType === 'ALWAYS';
  }

  /**
   * Check if this is a WHEN statement
   * @returns {boolean} True if WHEN
   */
  isWhen() {
    return this.logicType === 'WHEN';
  }

  /**
   * Check if this is an UNLESS statement
   * @returns {boolean} True if UNLESS
   */
  isUnless() {
    return this.logicType === 'UNLESS';
  }

  /**
   * Check if this is a REQUIRES statement
   * @returns {boolean} True if REQUIRES
   */
  isRequires() {
    return this.logicType === 'REQUIRES';
  }

  /**
   * Check if this is a strict rule (ALWAYS)
   * @returns {boolean} True if strict
   */
  isStrict() {
    return this.isAlways();
  }

  /**
   * Check if this is a defeasible rule (WHEN)
   * @returns {boolean} True if defeasible
   */
  isDefeasible() {
    return this.isWhen();
  }

  /**
   * Check if this is a defeater (UNLESS)
   * @returns {boolean} True if defeater
   */
  isDefeater() {
    return this.isUnless();
  }

  /**
   * Check if this is a requirement (REQUIRES)
   * @returns {boolean} True if requirement
   */
  isRequirement() {
    return this.isRequires();
  }

  /**
   * Get the precedence level for this logic type
   * @returns {number} Precedence level (higher = more important)
   */
  getPrecedence() {
    switch (this.logicType) {
      case 'ALWAYS': return 3; // Highest precedence
      case 'WHEN': return 2;   // Medium precedence
      case 'UNLESS': return 2; // Medium precedence
      case 'REQUIRES': return 1; // Lowest precedence
      default: return 0;
    }
  }

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

    // Validate logic type
    if (!['ALWAYS', 'WHEN', 'UNLESS', 'REQUIRES'].includes(this.logicType)) {
      errors.push(`Invalid logic type: ${this.logicType}`);
    }

    // Validate condition
    if (!this.condition) {
      errors.push(`${this.logicType} statement must have a condition`);
    } else {
      const condErrors = this.condition.validate ? this.condition.validate() : [];
      errors.push(...condErrors);
    }

    // Validate defeater for WHEN/UNLESS
    if ((this.isWhen() || this.isUnless()) && !this.defeater) {
      errors.push(`${this.logicType} statement must have a defeater`);
    }

    // Validate defeater if present
    if (this.defeater) {
      const defErrors = this.defeater.validate ? this.defeater.validate() : [];
      errors.push(...defErrors);
    }

    return errors;
  }

  toString() {
    const condStr = this.condition ? this.condition.toString() : 'null';
    const defStr = this.defeater ? ` UNLESS ${this.defeater.toString()}` : '';
    return `DefeasibleLogic(${this.logicType} ${condStr}${defStr})`;
  }
}
