import { getSetting } from "../db.js";

export const TriggerState = {
  untriggered: 0,
  replied: 1,
  canReply: 2,
  cannotReply: 3,
};

export function createTriggersChecklist() {
  return {
    'quoi': TriggerState.untriggered,
    'feur': TriggerState.untriggered,
    'mention': TriggerState.untriggered,
    'quoicoubeh': TriggerState.untriggered,
  };
}

// Base class for all detectors, using a Chain of Responsibility pattern
export default class Detector {
  nextDetector = null;
  triggerName = 'quoi'; // default value

  /**
   * @param nextDetector The detector that will be checked if this one doesn't detect anything
   * @returns The next detector
   */
  setNextDetector(nextDetector) {
    this.nextDetector = nextDetector;
    return nextDetector;
  }

  createSpecificReply(message) {
    return Promise.resolve(null);
  }

  getChanceToReply(message) {
    if (message.guildId == null) {
      return 0;
    }
    return getSetting(message.guildId, `${this.triggerName}AnswerPercentage`);
  }

  async createReply(message, triggersChecklist) {
    if (message.guildId == null) {
      return Promise.reject(new Error('No guild ID'));
    }

    const ignoredRoleId = getSetting(message.guildId, 'ignoredRoleId');
    if (ignoredRoleId !== null && message.member?.roles.cache.has(ignoredRoleId)) {
      return Promise.resolve('');
    }

    const forcedRoleId = getSetting(message.guildId, 'forcedAnswerRoleId');

    // if user has a forced role, skip the percentage (100%)
    const threshold = (forcedRoleId != null && message.member?.roles.cache.has(forcedRoleId)) 
      ? 100 
      : this.getChanceToReply(message);

    triggersChecklist = triggersChecklist ?? createTriggersChecklist();

    switch (triggersChecklist[this.triggerName]) {
      case TriggerState.replied:
        return Promise.resolve('');
      case TriggerState.untriggered:
        if (Math.floor(Math.random() * 100) < threshold) {
          triggersChecklist[this.triggerName] = TriggerState.canReply;
        } else {
          triggersChecklist[this.triggerName] = TriggerState.cannotReply;
        }
        break;
    }

    if (triggersChecklist[this.triggerName] === TriggerState.canReply) {
      const detected = await this.createSpecificReply(message);
      if (detected !== null) {
        triggersChecklist[this.triggerName] = TriggerState.replied;
        return detected;
      }
    }
    if (this.nextDetector) {
      return this.nextDetector.createReply(message, triggersChecklist);
    }
    return Promise.resolve('');
  }
}