/**
 * Text emoticon to emoji converter
 * Automatically converts common text emoticons like :) :D etc. to their emoji equivalents
 */

// Map of text emoticons to emoji
// Using common patterns that don't interfere with markdown links or other syntax
const EMOTICON_MAP: Record<string, string> = {
  // Happy faces
  ':D': '😀',
  ':-D': '😀',
  ':)': '🙂',
  ':-)': '🙂',
  '=)': '😊',
  ':]': '😊',
  ':>': '😊',
  
  // Sad faces
  ':(': '☹️',
  ':-(': '☹️',
  '=[': '☹️',
  ':<': '☹️',
  
  // Other emotions
  ';)': '😉',
  ';-)': '😉',
  ':P': '😛',
  ':-P': '😛',
  ':p': '😛',
  ':-p': '😛',
  'xD': '😆',
  'XD': '😆',
  ':|': '😐',
  ':-|': '😐',
  ':O': '😮',
  ':-O': '😮',
  ':o': '😮',
  ':-o': '😮',
  'O:)': '😇',
  'O:-)': '😇',
  ':*': '😘',
  ':-*': '😘',
  '<3': '❤️',
  '</3': '💔',
  
  // Surprised/Shocked
  ':0': '😯',
  ':-0': '😯',
  
  // Cool
  '8)': '😎',
  '8-)': '😎',
  'B)': '😎',
  'B-)': '😎',
  
  // Crying
  ':\'(': '😢',
  ':\')': '😂',
  
  // Neutral
  ':/': '😕',
  ':-/': '😕',
  ':\\': '😕',
  ':-\\': '😕',
};

/**
 * Converts text emoticons in a string to their emoji equivalents
 * Use backslash to escape: \:) will remain as :) without converting
 * @param text The text to process
 * @returns The text with emoticons converted to emoji
 */
export function convertEmoticons(text: string): string {
  let result = text;
  
  // Sort emoticons by length (longest first) to handle overlapping patterns
  // e.g., :-) before :)
  const emoticons = Object.keys(EMOTICON_MAP).sort((a, b) => b.length - a.length);
  
  for (const emoticon of emoticons) {
    // Escape special regex characters
    const escapedEmoticon = emoticon.replace(/[.*+?^${}()|[\]\\<>]/g, '\\$&');
    
    // Match emoticons with optional backslash escape
    // Matches either \:) (escaped) or :) (not escaped, and not preceded by backslash)
    const regex = new RegExp(
      `(^|\\s)(\\\\)?(${escapedEmoticon})(?=\\s|$)`,
      'g'
    );
    
    result = result.replace(regex, (match, prefix, backslash, emote) => {
      // If backslash is present, remove it but keep the emoticon literal
      if (backslash) {
        return prefix + emote;
      }
      // Otherwise convert to emoji
      return prefix + EMOTICON_MAP[emoticon];
    });
  }
  
  return result;
}

/**
 * Converts text emoticons in HTML to their emoji equivalents
 * Handles HTML entities like &lt; and &gt;
 * Use backslash to escape: \:) will remain as :) without converting
 * @param html The HTML text to process
 * @returns The HTML with emoticons converted to emoji
 */
export function convertEmoticonsInHtml(html: string): string {
  let result = html;
  
  // Sort emoticons by length (longest first) to handle overlapping patterns
  const emoticons = Object.keys(EMOTICON_MAP).sort((a, b) => b.length - a.length);
  
  for (const emoticon of emoticons) {
    // Convert emoticon to HTML entity version (for < and >)
    const htmlEmoticon = emoticon
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;');
    
    // Escape special regex characters
    const escapedEmoticon = htmlEmoticon.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    
    // Match emoticons at start of string, after whitespace, or after HTML tags
    // With optional backslash escape
    const regex = new RegExp(
      `(^|\\s|>)(\\\\)?(${escapedEmoticon})(?=\\s|<|$)`,
      'g'
    );
    
    result = result.replace(regex, (match, prefix, backslash, emote) => {
      // If backslash is present, remove it but keep the emoticon literal
      if (backslash) {
        return prefix + emote;
      }
      // Otherwise convert to emoji
      return prefix + EMOTICON_MAP[emoticon];
    });
  }
  
  return result;
}

/**
 * Checks if a string contains any text emoticons
 * @param text The text to check
 * @returns True if the text contains emoticons
 */
export function containsEmoticons(text: string): boolean {
  const emoticons = Object.keys(EMOTICON_MAP);
  
  for (const emoticon of emoticons) {
    const escapedEmoticon = emoticon.replace(/[.*+?^${}()|[\]\\<>]/g, '\\$&');
    const regex = new RegExp(`(^|\\s)(${escapedEmoticon})(?=\\s|$)`);
    
    if (regex.test(text)) {
      return true;
    }
  }
  
  return false;
}
