///|
pub struct DefinedName {
  name : String
  refers_to : String
  scope : String
  comment : String
} derive(Debug)

///|
pub fn DefinedName::new(
  name : String,
  refers_to : String,
  scope? : String = "",
  comment? : String = "",
) -> DefinedName {
  let scope_value = if scope == "" { "Workbook" } else { scope }
  { name, refers_to, scope: scope_value, comment }
}

///|
let max_field_length = 255

///|
let built_in_defined_names : Array[String] = [
  "_xlnm.Print_Area", "_xlnm.Print_Titles", "_xlnm.Criteria", "_xlnm._FilterDatabase",
  "_xlnm.Extract", "_xlnm.Consolidate_Area", "_xlnm.Database", "_xlnm.Sheet_Title",
]

///|
let supported_defined_name_start_ranges : Array[Int] = [
  65, 90, 92, 92, 95, 95, 97, 122, 161, 161, 164, 164, 167, 168, 170, 170, 173, 173,
  175, 186, 188, 696, 699, 705, 711, 711, 713, 715, 717, 717, 720, 721, 728, 731,
  733, 733, 736, 740, 750, 750, 880, 883, 886, 887, 890, 893, 902, 902, 904, 906,
  908, 908, 910, 929, 931, 1013, 1015, 1153, 1162, 1315, 1329, 1366, 1369, 1369,
  1377, 1415, 1488, 1514, 1520, 1522, 1569, 1610, 1646, 1647, 1649, 1747, 1749, 1749,
  1765, 1766, 1774, 1775, 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
  1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2308, 2361, 2365, 2365, 2384, 2384,
  2392, 2401, 2417, 2418, 2427, 2431, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480,
  2482, 2482, 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529, 2544, 2545,
  2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617,
  2649, 2652, 2654, 2654, 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
  2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785, 2821, 2828, 2831, 2832,
  2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913,
  2929, 2929, 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972,
  2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001, 3024, 3024, 3077, 3084, 3086, 3088,
  3090, 3112, 3114, 3123, 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
  3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261, 3294, 3294, 3296, 3297,
  3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3389, 3389, 3424, 3425, 3450, 3455,
  3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3642, 3648, 3662,
  3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
  3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773,
  3776, 3780, 3782, 3782, 3804, 3805, 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3979,
  4096, 4138, 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198, 4206, 4208,
  4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346, 4348, 4348, 4352, 4441, 4447, 4514,
  4520, 4601, 4608, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744,
  4746, 4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822,
  4824, 4880, 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740, 5743, 5750,
  5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5905, 5920, 5937, 5952, 5969,
  5984, 5996, 5998, 6000, 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
  6314, 6314, 6400, 6428, 6480, 6509, 6512, 6516, 6528, 6569, 6593, 6599, 6656, 6678,
  6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7168, 7203, 7245, 7247, 7258, 7293,
  7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025,
  8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132,
  8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, 8208, 8208,
  8211, 8214, 8216, 8216, 8220, 8221, 8224, 8225, 8229, 8231, 8240, 8240, 8242, 8243,
  8245, 8245, 8251, 8251, 8305, 8305, 8308, 8308, 8319, 8319, 8321, 8324, 8336, 8340,
  8450, 8451, 8453, 8453, 8455, 8455, 8457, 8467, 8469, 8470, 8473, 8477, 8481, 8482,
  8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
  8526, 8526, 8531, 8532, 8539, 8542, 8544, 8584, 8592, 8601, 8658, 8658, 8660, 8660,
  8704, 8704, 8706, 8707, 8711, 8712, 8715, 8715, 8719, 8719, 8721, 8721, 8725, 8725,
  8730, 8730, 8733, 8736, 8739, 8739, 8741, 8741, 8743, 8748, 8750, 8750, 8756, 8759,
  8764, 8765, 8776, 8776, 8780, 8780, 8786, 8786, 8800, 8801, 8804, 8807, 8810, 8811,
  8814, 8815, 8834, 8835, 8838, 8839, 8853, 8853, 8857, 8857, 8869, 8869, 8895, 8895,
  8978, 8978, 9312, 9397, 9424, 9449, 9472, 9547, 9552, 9588, 9601, 9615, 9618, 9621,
  9632, 9633, 9635, 9641, 9650, 9651, 9654, 9655, 9660, 9661, 9664, 9665, 9670, 9672,
  9675, 9675, 9678, 9681, 9698, 9701, 9711, 9711, 9733, 9734, 9737, 9737, 9742, 9743,
  9756, 9756, 9758, 9758, 9792, 9792, 9794, 9794, 9824, 9825, 9827, 9829, 9831, 9834,
  9836, 9837, 9839, 9839, 11264, 11310, 11312, 11358, 11360, 11375, 11377, 11389,
  11392, 11492, 11520, 11557, 11568, 11621, 11631, 11631, 11648, 11670, 11680, 11686,
  11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728, 11734,
  11736, 11742, 12288, 12291, 12293, 12311, 12317, 12319, 12321, 12329, 12337, 12341,
  12344, 12348, 12353, 12438, 12443, 12447, 12449, 12543, 12549, 12589, 12593, 12686,
  12704, 12727, 12784, 12828, 12832, 12841, 12849, 12850, 12857, 12857, 12896, 12923,
  12927, 12927, 12963, 12968, 13059, 13059, 13069, 13069, 13076, 13076, 13080, 13080,
  13090, 13091, 13094, 13095, 13099, 13099, 13110, 13110, 13115, 13115, 13129, 13130,
  13133, 13133, 13137, 13137, 13143, 13143, 13179, 13182, 13184, 13188, 13192, 13258,
  13261, 13267, 13269, 13270, 13272, 13272, 13275, 13277, 13312, 19893, 19968, 40899,
  40960, 42124, 42240, 42508, 42512, 42527, 42538, 42539, 42560, 42591, 42594, 42606,
  42624, 42647, 42786, 42887, 42891, 42892, 43003, 43009, 43011, 43013, 43015, 43018,
  43020, 43042, 43072, 43123, 43138, 43187, 43274, 43301, 43312, 43334, 43520, 43560,
  43584, 43586, 43588, 43595, 44032, 55203, 57344, 63560, 63744, 64045, 64048, 64106,
  64112, 64217, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310,
  64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829,
  64848, 64911, 64914, 64967, 65008, 65019, 65072, 65073, 65075, 65092, 65097, 65106,
  65108, 65111, 65113, 65126, 65128, 65131, 65136, 65140, 65142, 65276, 65281, 65374,
  65377, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, 65504, 65510,
]

///|
let supported_defined_name_after_ranges : Array[Int] = [
  46, 46, 48, 57, 63, 63, 65, 90, 92, 92, 95, 95, 97, 122, 161, 161, 164, 164, 167,
  168, 170, 170, 173, 173, 175, 186, 188, 887, 890, 893, 900, 902, 904, 906, 908,
  908, 910, 929, 931, 1315, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1469, 1471,
  1471, 1473, 1474, 1476, 1477, 1479, 1479, 1488, 1514, 1520, 1522, 1536, 1539, 1542,
  1544, 1547, 1547, 1550, 1562, 1567, 1567, 1569, 1630, 1632, 1641, 1646, 1747, 1749,
  1791, 1807, 1866, 1869, 1969, 1984, 2038, 2042, 2042, 2305, 2361, 2364, 2381, 2384,
  2388, 2392, 2403, 2406, 2415, 2417, 2418, 2427, 2431, 2433, 2435, 2437, 2444, 2447,
  2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2500, 2503, 2504, 2507,
  2510, 2519, 2519, 2524, 2525, 2527, 2531, 2534, 2554, 2561, 2563, 2565, 2570, 2575,
  2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622,
  2626, 2631, 2632, 2635, 2637, 2641, 2641, 2649, 2652, 2654, 2654, 2662, 2677, 2689,
  2691, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748,
  2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, 2787, 2790, 2799, 2801, 2801, 2817,
  2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2869, 2873, 2876,
  2884, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2915, 2918, 2929, 2946,
  2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979,
  2980, 2984, 2986, 2990, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3024, 3024, 3031,
  3031, 3046, 3066, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125,
  3129, 3133, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3160, 3161, 3168, 3171, 3174,
  3183, 3192, 3199, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253,
  3257, 3260, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3299, 3302,
  3311, 3313, 3314, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3389,
  3396, 3398, 3400, 3402, 3405, 3415, 3415, 3424, 3427, 3430, 3445, 3449, 3455, 3458,
  3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, 3535,
  3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3647, 3662, 3664, 3673, 3713,
  3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745,
  3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782,
  3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3843, 3859, 3897, 3902, 3911, 3913,
  3948, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4030, 4044, 4046, 4047, 4096,
  4169, 4176, 4249, 4254, 4293, 4304, 4346, 4348, 4348, 4352, 4441, 4447, 4514, 4520,
  4601, 4608, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, 4744, 4746,
  4749, 4752, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824,
  4880, 4882, 4885, 4888, 4954, 4959, 4960, 4969, 4988, 4992, 5017, 5024, 5108, 5121,
  5740, 5743, 5750, 5760, 5786, 5792, 5866, 5870, 5872, 5888, 5900, 5902, 5908, 5920,
  5940, 5952, 5971, 5984, 5996, 5998, 6000, 6002, 6003, 6016, 6099, 6103, 6103, 6107,
  6109, 6112, 6121, 6128, 6137, 6155, 6158, 6160, 6169, 6176, 6263, 6272, 6314, 6400,
  6428, 6432, 6443, 6448, 6459, 6464, 6464, 6470, 6509, 6512, 6516, 6528, 6569, 6576,
  6601, 6608, 6617, 6624, 6683, 6912, 6987, 6992, 7001, 7009, 7036, 7040, 7082, 7086,
  7097, 7168, 7223, 7232, 7241, 7245, 7293, 7424, 7654, 7678, 7957, 7960, 7965, 7968,
  8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064,
  8116, 8118, 8132, 8134, 8147, 8150, 8155, 8157, 8175, 8178, 8180, 8182, 8190, 8192,
  8208, 8211, 8214, 8216, 8216, 8220, 8221, 8224, 8225, 8229, 8240, 8242, 8243, 8245,
  8245, 8251, 8251, 8260, 8260, 8274, 8274, 8287, 8292, 8298, 8305, 8308, 8316, 8319,
  8332, 8336, 8340, 8352, 8373, 8400, 8432, 8448, 8527, 8531, 8584, 8592, 9000, 9003,
  9191, 9216, 9254, 9280, 9290, 9312, 9885, 9888, 9916, 9920, 9923, 9985, 9988, 9990,
  9993, 9996, 10023, 10025, 10059, 10061, 10061, 10063, 10066, 10070, 10070, 10072,
  10078, 10081, 10087, 10102, 10132, 10136, 10159, 10161, 10174, 10176, 10180, 10183,
  10186, 10188, 10188, 10192, 10213, 10224, 10626, 10649, 10711, 10716, 10747, 10750,
  11084, 11088, 11092, 11264, 11310, 11312, 11358, 11360, 11375, 11377, 11389, 11392,
  11498, 11517, 11517, 11520, 11557, 11568, 11621, 11631, 11631, 11648, 11670, 11680,
  11686, 11688, 11694, 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726, 11728,
  11734, 11736, 11742, 11744, 11775, 11823, 11823, 11904, 11929, 11931, 12019, 12032,
  12245, 12272, 12283, 12288, 12311, 12317, 12335, 12337, 12348, 12350, 12351, 12353,
  12438, 12441, 12447, 12449, 12543, 12549, 12589, 12593, 12686, 12688, 12727, 12736,
  12771, 12784, 12830, 12832, 12867, 12880, 13054, 13056, 19893, 19904, 40899, 40960,
  42124, 42128, 42182, 42240, 42508, 42512, 42539, 42560, 42591, 42594, 42610, 42620,
  42621, 42623, 42647, 42752, 42892, 43003, 43051, 43072, 43123, 43136, 43204, 43216,
  43225, 43264, 43310, 43312, 43347, 43520, 43574, 43584, 43597, 43600, 43609, 44032,
  55203, 55296, 64045, 64048, 64106, 64112, 64217, 64256, 64262, 64275, 64279, 64285,
  64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467,
  64829, 64848, 64911, 64914, 64967, 65008, 65021, 65024, 65039, 65056, 65062, 65072,
  65073, 65075, 65092, 65097, 65106, 65108, 65111, 65113, 65126, 65128, 65131, 65136,
  65140, 65142, 65276, 65279, 65279, 65281, 65374, 65377, 65470, 65474, 65479, 65482,
  65487, 65490, 65495, 65498, 65500, 65504, 65510, 65512, 65518, 65529, 65533,
]

///|
fn in_code_range(value : Int, ranges : Array[Int]) -> Bool {
  let mut i = 0
  while i + 1 < ranges.length() {
    if ranges[i] <= value && value <= ranges[i + 1] {
      return true
    }
    i = i + 2
  }
  false
}

///|
fn normalize_defined_name_scope(scope : StringView) -> String {
  if scope == "" {
    "Workbook"
  } else {
    scope.to_owned()
  }
}

///|
fn is_builtin_defined_name(name : StringView) -> Bool {
  for i in 0..<2 {
    if i < built_in_defined_names.length() && name == built_in_defined_names[i] {
      return true
    }
  }
  false
}

///|
fn check_defined_name(name : StringView) -> Unit raise XlsxError {
  if count_utf16_units(name) > max_field_length {
    raise InvalidDefinedName(msg="defined name too long")
  }
  let mut first = true
  for c in name {
    let code = c.to_int()
    if first {
      if in_code_range(code, supported_defined_name_start_ranges) {
        first = false
        continue
      }
      raise InvalidDefinedName(msg="defined name invalid")
    }
    if in_code_range(code, supported_defined_name_after_ranges) {
      continue
    }
    raise InvalidDefinedName(msg="defined name invalid")
  }
}

///|
fn escape_sheet_name(name : StringView) -> String {
  name.to_owned().replace_all(old="'", new="''")
}

///|
fn replace_sheet_name_in_refers_to(
  refers_to : StringView,
  from_name : StringView,
  to_name : StringView,
) -> String {
  let raw = refers_to.to_owned()
  let quoted_from = "'\{escape_sheet_name(from_name)}'!"
  let quoted_to = "'\{escape_sheet_name(to_name)}'!"
  let plain_from = "\{from_name.to_owned()}!"
  let plain_to = "\{to_name.to_owned()}!"
  raw
  .replace_all(old=quoted_from, new=quoted_to)
  .replace_all(old=plain_from, new=plain_to)
}

///|
test "defined name wb: normalize empty scope to Workbook" {
  inspect(normalize_defined_name_scope(""), content="Workbook")
}

///|
test "defined name wb: builtin name detection includes print area" {
  inspect(is_builtin_defined_name("_xlnm.Print_Area"), content="true")
}

///|
test "defined name wb: reject too-long names" {
  let too_long : Result[Unit, Error] = Ok(check_defined_name("a".repeat(256))) catch {
    e => Err(e)
  }
  inspect(too_long is Err(XlsxError::InvalidDefinedName(_)), content="true")
}