@IsTest
public class StringUtilTest {

  @IsTest
  static void testGetFirstName() {
    System.assertEquals('Test', StringUtil.getFirstName('Test'));
    System.assertEquals('Test', StringUtil.getFirstName('Test User'));
    System.assertEquals('Test', StringUtil.getFirstName('Test User Jr.'));
    System.assertEquals(null, StringUtil.getFirstName(null));
  }

  @IsTest
  static void testGetLastName() {
    System.assertEquals('Test', StringUtil.getLastName('Test'));
    System.assertEquals('User', StringUtil.getLastName('Test User'));
    System.assertEquals('User Jr.', StringUtil.getLastName('Test User Jr.'));
    System.assertEquals(null, StringUtil.getLastName(null));
  }

  @IsTest
  static void testFormatPhoneNumber() {
    String expectedOutput = '(123) 456-7890';
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('(123) 456-7890'));
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('123-456-7890'));
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('123 456-7890'));
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('1234567890'));
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('+1234567890'));
    System.assertEquals(expectedOutput, StringUtil.formatPhoneNumber('+1 123-456-7890'));
    System.assertEquals('456-7890', StringUtil.formatPhoneNumber('4567890'));
    System.assertEquals('123 123-456-7890', StringUtil.formatPhoneNumber('123 123-456-7890'));
    System.assertEquals(null, StringUtil.formatPhoneNumber(null));
  }

  @IsTest
  static void testGetIndefiniteArticle() {
    System.assertEquals('a', StringUtil.getIndefiniteArticle('Contact'));
    System.assertEquals('an', StringUtil.getIndefiniteArticle('Account'));
    System.assertEquals('an', StringUtil.getIndefiniteArticle('Opportunity'));
  }

  @IsTest
  static void testMogrifyJSON() {
    Map<String, Object> expectedOutput = new Map<String, Object>{
      'case_x' => 'testCase'
    };
    Map<String, Object> res = new Map<String, Object>{
      'case' => 'testCase'
    };
    Map<String, String> replacements = new Map<String, String>{
      'case' => 'case_x'
    };
    String json = System.JSON.serialize(res);
    String result = StringUtil.mogrifyJSON(json, replacements);
    // TODO: check if this is correct
    // System.assertEquals(System.JSON.serializePretty(expectedOutput), StringUtil.mogrifyJSON(json, replacements));
    // System.assertEquals('{ "case_x" : "testCase" }', StringUtil.mogrifyJSON(json, replacements));
  }

  @IsTest
  static void testToTitleCase() {
    String expectedOutput = 'This is Awesome Dude';
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('This is Awesome Dude'));
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('this is awesome dude'));
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('This is awesome dude'));
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('this Is awesome dude'));
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('this is Awesome dude'));
    System.assertEquals(expectedOutput, StringUtil.toTitleCase('this is awesome Dude'));
    System.assertEquals('Name', StringUtil.toTitleCase('name'));
    System.assertEquals(null, StringUtil.toTitleCase(null));
  }

  @IsTest
  static void testNormalizeKeys() {
    String input = '{"and": "test", "while": "test"}';
    String expectedOutput = '{"andx": "test", "whilex": "test"}';
    System.assertEquals(expectedOutput, StringUtil.normalizeKeys(input));
  }

  @IsTest
  static void testSafeSplit() {
    List<String> expectedOutput = new List<String>{'test1', 'test2'};
    System.assertEquals(expectedOutput, StringUtil.safeSplit('test1,test2', ','));
  }

  @IsTest
  static void testIsIpAddress() {
    // ipv4
    System.assertEquals(true, StringUtil.isIpAddress('0.0.0.0'));
    System.assertEquals(true, StringUtil.isIpAddress('192.168.10.1'));
    System.assertEquals(false, StringUtil.isIpAddress('256.0.0.0'));
    System.assertEquals(false, StringUtil.isIpAddress('0.0.0.256'));
    // ipv6
    System.assertEquals(true, StringUtil.isIpAddress('2001:0db8:85a3:0000:0000:8a2e:0370:7334'));
    System.assertEquals(true, StringUtil.isIpAddress('2001:db8:85a3:0:0:8a2e:370:7334'));
    // System.assertEquals(true, StringUtil.isIpAddress('2001:db8:85a3::8a2e:370:7334'));
    System.assertEquals(false, StringUtil.isIpAddress('2001:0db8:85a3:0000:0000:8a2e:0370:733g'));
    // false tests
    System.assertEquals(false, StringUtil.isIpAddress('dude sweet'));
    System.assertEquals(false, StringUtil.isIpAddress('dude.sweet.dude.sweet'));
    System.assertEquals(false, StringUtil.isIpAddress(null));
  }

  @IsTest
  static void testIsEmailAddress() {
    System.assertEquals(true, StringUtil.isEmailAddress('test@test.com'));
    System.assertEquals(true, StringUtil.isEmailAddress('test.dev@test.com'));
    System.assertEquals(true, StringUtil.isEmailAddress('test@t.com'));
    System.assertEquals(false, StringUtil.isEmailAddress('test'));
    System.assertEquals(false, StringUtil.isEmailAddress('test.test.com'));
    System.assertEquals(false, StringUtil.isEmailAddress('a@b@c@test.com'));
    System.assertEquals(false, StringUtil.isEmailAddress('test@outlook.'));
    System.assertEquals(false, StringUtil.isEmailAddress(null));
  }

}