///|
pub fn timing_catalog() -> Array[TimingCatalogEntry] {
  [
    timing_entry(
      "est-720x400-70",
      EstablishedFamily,
      720,
      400,
      70000,
      28320,
      true,
      "9:5",
      "Established 720x400@70",
    ),
    timing_entry(
      "est-720x400-88",
      EstablishedFamily,
      720,
      400,
      88000,
      35500,
      true,
      "9:5",
      "Established 720x400@88",
    ),
    timing_entry(
      "est-640x480-60",
      EstablishedFamily,
      640,
      480,
      60000,
      25175,
      true,
      "4:3",
      "Established 640x480@60",
    ),
    timing_entry(
      "est-640x480-67",
      EstablishedFamily,
      640,
      480,
      67000,
      30240,
      true,
      "4:3",
      "Established 640x480@67",
    ),
    timing_entry(
      "est-640x480-72",
      EstablishedFamily,
      640,
      480,
      72000,
      31500,
      true,
      "4:3",
      "Established 640x480@72",
    ),
    timing_entry(
      "est-640x480-75",
      EstablishedFamily,
      640,
      480,
      75000,
      31500,
      true,
      "4:3",
      "Established 640x480@75",
    ),
    timing_entry(
      "est-800x600-56",
      EstablishedFamily,
      800,
      600,
      56000,
      36000,
      true,
      "4:3",
      "Established 800x600@56",
    ),
    timing_entry(
      "est-800x600-60",
      EstablishedFamily,
      800,
      600,
      60000,
      40000,
      true,
      "4:3",
      "Established 800x600@60",
    ),
    timing_entry(
      "est-800x600-72",
      EstablishedFamily,
      800,
      600,
      72000,
      50000,
      true,
      "4:3",
      "Established 800x600@72",
    ),
    timing_entry(
      "est-800x600-75",
      EstablishedFamily,
      800,
      600,
      75000,
      49500,
      true,
      "4:3",
      "Established 800x600@75",
    ),
    timing_entry(
      "est-832x624-75",
      EstablishedFamily,
      832,
      624,
      75000,
      57284,
      true,
      "4:3",
      "Established 832x624@75",
    ),
    timing_entry(
      "est-1024x768-87i",
      EstablishedFamily,
      1024,
      768,
      87000,
      44900,
      false,
      "4:3",
      "Established 1024x768@87i",
    ),
    timing_entry(
      "est-1024x768-60",
      EstablishedFamily,
      1024,
      768,
      60000,
      65000,
      true,
      "4:3",
      "Established 1024x768@60",
    ),
    timing_entry(
      "est-1024x768-70",
      EstablishedFamily,
      1024,
      768,
      70000,
      75000,
      true,
      "4:3",
      "Established 1024x768@70",
    ),
    timing_entry(
      "est-1024x768-75",
      EstablishedFamily,
      1024,
      768,
      75000,
      78750,
      true,
      "4:3",
      "Established 1024x768@75",
    ),
    timing_entry(
      "est-1280x1024-75",
      EstablishedFamily,
      1280,
      1024,
      75000,
      135000,
      true,
      "5:4",
      "Established 1280x1024@75",
    ),
    timing_entry(
      "est-1152x870-75",
      EstablishedFamily,
      1152,
      870,
      75000,
      100000,
      true,
      "4:3",
      "Established 1152x870@75",
    ),
    timing_entry(
      "dmt-640x350-85",
      DmtFamily,
      640,
      350,
      85000,
      31500,
      true,
      "64:35",
      "DMT 640x350@85",
    ),
    timing_entry(
      "dmt-640x400-85",
      DmtFamily,
      640,
      400,
      85000,
      31500,
      true,
      "16:10",
      "DMT 640x400@85",
    ),
    timing_entry(
      "dmt-720x400-70",
      DmtFamily,
      720,
      400,
      70000,
      28320,
      true,
      "9:5",
      "DMT 720x400@70",
    ),
    timing_entry(
      "dmt-720x400-85",
      DmtFamily,
      720,
      400,
      85000,
      35500,
      true,
      "9:5",
      "DMT 720x400@85",
    ),
    timing_entry(
      "dmt-640x480-60",
      DmtFamily,
      640,
      480,
      60000,
      25175,
      true,
      "4:3",
      "DMT 640x480@60",
    ),
    timing_entry(
      "dmt-640x480-72",
      DmtFamily,
      640,
      480,
      72000,
      31500,
      true,
      "4:3",
      "DMT 640x480@72",
    ),
    timing_entry(
      "dmt-640x480-75",
      DmtFamily,
      640,
      480,
      75000,
      31500,
      true,
      "4:3",
      "DMT 640x480@75",
    ),
    timing_entry(
      "dmt-640x480-85",
      DmtFamily,
      640,
      480,
      85000,
      36000,
      true,
      "4:3",
      "DMT 640x480@85",
    ),
    timing_entry(
      "dmt-800x600-56",
      DmtFamily,
      800,
      600,
      56000,
      36000,
      true,
      "4:3",
      "DMT 800x600@56",
    ),
    timing_entry(
      "dmt-800x600-60",
      DmtFamily,
      800,
      600,
      60000,
      40000,
      true,
      "4:3",
      "DMT 800x600@60",
    ),
    timing_entry(
      "dmt-800x600-72",
      DmtFamily,
      800,
      600,
      72000,
      50000,
      true,
      "4:3",
      "DMT 800x600@72",
    ),
    timing_entry(
      "dmt-800x600-75",
      DmtFamily,
      800,
      600,
      75000,
      49500,
      true,
      "4:3",
      "DMT 800x600@75",
    ),
    timing_entry(
      "dmt-800x600-85",
      DmtFamily,
      800,
      600,
      85000,
      56250,
      true,
      "4:3",
      "DMT 800x600@85",
    ),
    timing_entry(
      "dmt-848x480-60",
      DmtFamily,
      848,
      480,
      60000,
      33750,
      true,
      "16:9",
      "DMT 848x480@60",
    ),
    timing_entry(
      "dmt-1024x768-87i",
      DmtFamily,
      1024,
      768,
      87000,
      44900,
      false,
      "4:3",
      "DMT 1024x768@87i",
    ),
    timing_entry(
      "dmt-1024x768-60",
      DmtFamily,
      1024,
      768,
      60000,
      65000,
      true,
      "4:3",
      "DMT 1024x768@60",
    ),
    timing_entry(
      "dmt-1024x768-70",
      DmtFamily,
      1024,
      768,
      70000,
      75000,
      true,
      "4:3",
      "DMT 1024x768@70",
    ),
    timing_entry(
      "dmt-1024x768-75",
      DmtFamily,
      1024,
      768,
      75000,
      78750,
      true,
      "4:3",
      "DMT 1024x768@75",
    ),
    timing_entry(
      "dmt-1024x768-85",
      DmtFamily,
      1024,
      768,
      85000,
      94500,
      true,
      "4:3",
      "DMT 1024x768@85",
    ),
    timing_entry(
      "dmt-1152x864-75",
      DmtFamily,
      1152,
      864,
      75000,
      108000,
      true,
      "4:3",
      "DMT 1152x864@75",
    ),
    timing_entry(
      "dmt-1280x768-60",
      DmtFamily,
      1280,
      768,
      60000,
      79500,
      true,
      "5:3",
      "DMT 1280x768@60",
    ),
    timing_entry(
      "dmt-1280x768-75",
      DmtFamily,
      1280,
      768,
      75000,
      102250,
      true,
      "5:3",
      "DMT 1280x768@75",
    ),
    timing_entry(
      "dmt-1280x768-85",
      DmtFamily,
      1280,
      768,
      85000,
      117500,
      true,
      "5:3",
      "DMT 1280x768@85",
    ),
    timing_entry(
      "dmt-1280x800-60",
      DmtFamily,
      1280,
      800,
      60000,
      83500,
      true,
      "16:10",
      "DMT 1280x800@60",
    ),
    timing_entry(
      "dmt-1280x800-75",
      DmtFamily,
      1280,
      800,
      75000,
      106500,
      true,
      "16:10",
      "DMT 1280x800@75",
    ),
    timing_entry(
      "dmt-1280x800-85",
      DmtFamily,
      1280,
      800,
      85000,
      122500,
      true,
      "16:10",
      "DMT 1280x800@85",
    ),
    timing_entry(
      "dmt-1280x960-60",
      DmtFamily,
      1280,
      960,
      60000,
      108000,
      true,
      "4:3",
      "DMT 1280x960@60",
    ),
    timing_entry(
      "dmt-1280x960-85",
      DmtFamily,
      1280,
      960,
      85000,
      148500,
      true,
      "4:3",
      "DMT 1280x960@85",
    ),
    timing_entry(
      "dmt-1280x1024-60",
      DmtFamily,
      1280,
      1024,
      60000,
      108000,
      true,
      "5:4",
      "DMT 1280x1024@60",
    ),
    timing_entry(
      "dmt-1280x1024-75",
      DmtFamily,
      1280,
      1024,
      75000,
      135000,
      true,
      "5:4",
      "DMT 1280x1024@75",
    ),
    timing_entry(
      "dmt-1280x1024-85",
      DmtFamily,
      1280,
      1024,
      85000,
      157500,
      true,
      "5:4",
      "DMT 1280x1024@85",
    ),
    timing_entry(
      "dmt-1360x768-60",
      DmtFamily,
      1360,
      768,
      60000,
      85500,
      true,
      "16:9",
      "DMT 1360x768@60",
    ),
    timing_entry(
      "dmt-1366x768-60",
      DmtFamily,
      1366,
      768,
      60000,
      85500,
      true,
      "16:9",
      "DMT 1366x768@60",
    ),
    timing_entry(
      "dmt-1400x1050-60",
      DmtFamily,
      1400,
      1050,
      60000,
      121750,
      true,
      "4:3",
      "DMT 1400x1050@60",
    ),
    timing_entry(
      "dmt-1400x1050-75",
      DmtFamily,
      1400,
      1050,
      75000,
      156000,
      true,
      "4:3",
      "DMT 1400x1050@75",
    ),
    timing_entry(
      "dmt-1400x1050-85",
      DmtFamily,
      1400,
      1050,
      85000,
      179500,
      true,
      "4:3",
      "DMT 1400x1050@85",
    ),
    timing_entry(
      "dmt-1440x900-60",
      DmtFamily,
      1440,
      900,
      60000,
      106500,
      true,
      "16:10",
      "DMT 1440x900@60",
    ),
    timing_entry(
      "dmt-1440x900-75",
      DmtFamily,
      1440,
      900,
      75000,
      136750,
      true,
      "16:10",
      "DMT 1440x900@75",
    ),
    timing_entry(
      "dmt-1440x900-85",
      DmtFamily,
      1440,
      900,
      85000,
      157000,
      true,
      "16:10",
      "DMT 1440x900@85",
    ),
    timing_entry(
      "dmt-1600x900-60",
      DmtFamily,
      1600,
      900,
      60000,
      108000,
      true,
      "16:9",
      "DMT 1600x900@60",
    ),
    timing_entry(
      "dmt-1600x1200-60",
      DmtFamily,
      1600,
      1200,
      60000,
      162000,
      true,
      "4:3",
      "DMT 1600x1200@60",
    ),
    timing_entry(
      "dmt-1600x1200-65",
      DmtFamily,
      1600,
      1200,
      65000,
      175500,
      true,
      "4:3",
      "DMT 1600x1200@65",
    ),
    timing_entry(
      "dmt-1600x1200-70",
      DmtFamily,
      1600,
      1200,
      70000,
      189000,
      true,
      "4:3",
      "DMT 1600x1200@70",
    ),
    timing_entry(
      "dmt-1600x1200-75",
      DmtFamily,
      1600,
      1200,
      75000,
      202500,
      true,
      "4:3",
      "DMT 1600x1200@75",
    ),
    timing_entry(
      "dmt-1600x1200-85",
      DmtFamily,
      1600,
      1200,
      85000,
      229500,
      true,
      "4:3",
      "DMT 1600x1200@85",
    ),
    timing_entry(
      "dmt-1680x1050-60",
      DmtFamily,
      1680,
      1050,
      60000,
      146250,
      true,
      "16:10",
      "DMT 1680x1050@60",
    ),
    timing_entry(
      "dmt-1680x1050-75",
      DmtFamily,
      1680,
      1050,
      75000,
      187000,
      true,
      "16:10",
      "DMT 1680x1050@75",
    ),
    timing_entry(
      "dmt-1680x1050-85",
      DmtFamily,
      1680,
      1050,
      85000,
      214750,
      true,
      "16:10",
      "DMT 1680x1050@85",
    ),
    timing_entry(
      "dmt-1792x1344-60",
      DmtFamily,
      1792,
      1344,
      60000,
      204750,
      true,
      "4:3",
      "DMT 1792x1344@60",
    ),
    timing_entry(
      "dmt-1792x1344-75",
      DmtFamily,
      1792,
      1344,
      75000,
      261000,
      true,
      "4:3",
      "DMT 1792x1344@75",
    ),
    timing_entry(
      "dmt-1856x1392-60",
      DmtFamily,
      1856,
      1392,
      60000,
      218250,
      true,
      "4:3",
      "DMT 1856x1392@60",
    ),
    timing_entry(
      "dmt-1856x1392-75",
      DmtFamily,
      1856,
      1392,
      75000,
      288000,
      true,
      "4:3",
      "DMT 1856x1392@75",
    ),
    timing_entry(
      "dmt-1920x1080-60",
      DmtFamily,
      1920,
      1080,
      60000,
      148500,
      true,
      "16:9",
      "DMT 1920x1080@60",
    ),
    timing_entry(
      "dmt-1920x1200-60",
      DmtFamily,
      1920,
      1200,
      60000,
      193250,
      true,
      "16:10",
      "DMT 1920x1200@60",
    ),
    timing_entry(
      "dmt-1920x1200-75",
      DmtFamily,
      1920,
      1200,
      75000,
      245250,
      true,
      "16:10",
      "DMT 1920x1200@75",
    ),
    timing_entry(
      "dmt-1920x1200-85",
      DmtFamily,
      1920,
      1200,
      85000,
      281250,
      true,
      "16:10",
      "DMT 1920x1200@85",
    ),
    timing_entry(
      "dmt-1920x1440-60",
      DmtFamily,
      1920,
      1440,
      60000,
      234000,
      true,
      "4:3",
      "DMT 1920x1440@60",
    ),
    timing_entry(
      "dmt-1920x1440-75",
      DmtFamily,
      1920,
      1440,
      75000,
      297000,
      true,
      "4:3",
      "DMT 1920x1440@75",
    ),
    timing_entry(
      "dmt-2048x1152-60",
      DmtFamily,
      2048,
      1152,
      60000,
      162000,
      true,
      "16:9",
      "DMT 2048x1152@60",
    ),
    timing_entry(
      "dmt-2560x1440-60",
      DmtFamily,
      2560,
      1440,
      60000,
      241500,
      true,
      "16:9",
      "DMT 2560x1440@60",
    ),
    timing_entry(
      "dmt-2560x1600-60",
      DmtFamily,
      2560,
      1600,
      60000,
      268500,
      true,
      "16:10",
      "DMT 2560x1600@60",
    ),
    timing_entry(
      "cta-640x480-60",
      CtaFamily,
      640,
      480,
      60000,
      25175,
      true,
      "4:3",
      "CTA VIC 1 640x480@60",
    ),
    timing_entry(
      "cta-720x480-60",
      CtaFamily,
      720,
      480,
      60000,
      27000,
      true,
      "3:2",
      "CTA VIC 2 720x480@60",
    ),
    timing_entry(
      "cta-1280x720-60",
      CtaFamily,
      1280,
      720,
      60000,
      74250,
      true,
      "16:9",
      "CTA VIC 4 1280x720@60",
    ),
    timing_entry(
      "cta-1920x1080-60i",
      CtaFamily,
      1920,
      1080,
      60000,
      74250,
      false,
      "16:9",
      "CTA VIC 5 1920x1080@60i",
    ),
    timing_entry(
      "cta-720x480-60w",
      CtaFamily,
      720,
      480,
      60000,
      27000,
      true,
      "16:9",
      "CTA VIC 3 720x480@60",
    ),
    timing_entry(
      "cta-720x576-50",
      CtaFamily,
      720,
      576,
      50000,
      27000,
      true,
      "4:3",
      "CTA VIC 17 720x576@50",
    ),
    timing_entry(
      "cta-1280x720-50",
      CtaFamily,
      1280,
      720,
      50000,
      74250,
      true,
      "16:9",
      "CTA VIC 19 1280x720@50",
    ),
    timing_entry(
      "cta-1920x1080-50i",
      CtaFamily,
      1920,
      1080,
      50000,
      74250,
      false,
      "16:9",
      "CTA VIC 20 1920x1080@50i",
    ),
    timing_entry(
      "cta-1920x1080-24",
      CtaFamily,
      1920,
      1080,
      24000,
      74250,
      true,
      "16:9",
      "CTA VIC 32 1920x1080@24",
    ),
    timing_entry(
      "cta-1920x1080-25",
      CtaFamily,
      1920,
      1080,
      25000,
      74250,
      true,
      "16:9",
      "CTA VIC 33 1920x1080@25",
    ),
    timing_entry(
      "cta-1920x1080-30",
      CtaFamily,
      1920,
      1080,
      30000,
      74250,
      true,
      "16:9",
      "CTA VIC 34 1920x1080@30",
    ),
    timing_entry(
      "cta-1920x1080-50",
      CtaFamily,
      1920,
      1080,
      50000,
      148500,
      true,
      "16:9",
      "CTA VIC 31 1920x1080@50",
    ),
    timing_entry(
      "cta-1920x1080-60",
      CtaFamily,
      1920,
      1080,
      60000,
      148500,
      true,
      "16:9",
      "CTA VIC 16 1920x1080@60",
    ),
    timing_entry(
      "cta-3840x2160-24",
      CtaFamily,
      3840,
      2160,
      24000,
      297000,
      true,
      "16:9",
      "CTA VIC 93 3840x2160@24",
    ),
    timing_entry(
      "cta-3840x2160-25",
      CtaFamily,
      3840,
      2160,
      25000,
      297000,
      true,
      "16:9",
      "CTA VIC 94 3840x2160@25",
    ),
    timing_entry(
      "cta-3840x2160-30",
      CtaFamily,
      3840,
      2160,
      30000,
      297000,
      true,
      "16:9",
      "CTA VIC 95 3840x2160@30",
    ),
    timing_entry(
      "cta-3840x2160-50",
      CtaFamily,
      3840,
      2160,
      50000,
      594000,
      true,
      "16:9",
      "CTA VIC 96 3840x2160@50",
    ),
    timing_entry(
      "cta-3840x2160-60",
      CtaFamily,
      3840,
      2160,
      60000,
      594000,
      true,
      "16:9",
      "CTA VIC 97 3840x2160@60",
    ),
    timing_entry(
      "cta-4096x2160-24",
      CtaFamily,
      4096,
      2160,
      24000,
      297000,
      true,
      "256:135",
      "CTA VIC 98 4096x2160@24",
    ),
    timing_entry(
      "cta-4096x2160-25",
      CtaFamily,
      4096,
      2160,
      25000,
      297000,
      true,
      "256:135",
      "CTA VIC 99 4096x2160@25",
    ),
    timing_entry(
      "cta-4096x2160-30",
      CtaFamily,
      4096,
      2160,
      30000,
      297000,
      true,
      "256:135",
      "CTA VIC 100 4096x2160@30",
    ),
    timing_entry(
      "cta-4096x2160-50",
      CtaFamily,
      4096,
      2160,
      50000,
      594000,
      true,
      "256:135",
      "CTA VIC 101 4096x2160@50",
    ),
    timing_entry(
      "cta-4096x2160-60",
      CtaFamily,
      4096,
      2160,
      60000,
      594000,
      true,
      "256:135",
      "CTA VIC 102 4096x2160@60",
    ),
    timing_entry(
      "cvt-1024x576-60",
      CvtFamily,
      1024,
      576,
      60000,
      46500,
      true,
      "16:9",
      "CVT 1024x576@60",
    ),
    timing_entry(
      "cvt-1152x648-60",
      CvtFamily,
      1152,
      648,
      60000,
      62500,
      true,
      "16:9",
      "CVT 1152x648@60",
    ),
    timing_entry(
      "cvt-1280x720-60",
      CvtFamily,
      1280,
      720,
      60000,
      74500,
      true,
      "16:9",
      "CVT 1280x720@60",
    ),
    timing_entry(
      "cvt-1366x768-60",
      CvtFamily,
      1366,
      768,
      60000,
      85500,
      true,
      "16:9",
      "CVT 1366x768@60",
    ),
    timing_entry(
      "cvt-1600x900-60",
      CvtFamily,
      1600,
      900,
      60000,
      119000,
      true,
      "16:9",
      "CVT 1600x900@60",
    ),
    timing_entry(
      "cvt-1920x1080-60",
      CvtFamily,
      1920,
      1080,
      60000,
      173000,
      true,
      "16:9",
      "CVT 1920x1080@60",
    ),
    timing_entry(
      "cvt-2560x1440-60",
      CvtFamily,
      2560,
      1440,
      60000,
      312250,
      true,
      "16:9",
      "CVT 2560x1440@60",
    ),
    timing_entry(
      "cvt-3440x1440-60",
      CvtFamily,
      3440,
      1440,
      60000,
      419500,
      true,
      "43:18",
      "CVT 3440x1440@60",
    ),
    timing_entry(
      "cvt-3840x2160-60",
      CvtFamily,
      3840,
      2160,
      60000,
      712750,
      true,
      "16:9",
      "CVT 3840x2160@60",
    ),
    timing_entry(
      "rb-1280x720-60",
      RbFamily,
      1280,
      720,
      60000,
      60000,
      true,
      "16:9",
      "CVT-RB 1280x720@60",
    ),
    timing_entry(
      "rb-1366x768-60",
      RbFamily,
      1366,
      768,
      60000,
      72000,
      true,
      "16:9",
      "CVT-RB 1366x768@60",
    ),
    timing_entry(
      "rb-1600x900-60",
      RbFamily,
      1600,
      900,
      60000,
      97000,
      true,
      "16:9",
      "CVT-RB 1600x900@60",
    ),
    timing_entry(
      "rb-1920x1080-60",
      RbFamily,
      1920,
      1080,
      60000,
      138500,
      true,
      "16:9",
      "CVT-RB 1920x1080@60",
    ),
    timing_entry(
      "rb-1920x1200-60",
      RbFamily,
      1920,
      1200,
      60000,
      154000,
      true,
      "16:10",
      "CVT-RB 1920x1200@60",
    ),
    timing_entry(
      "rb-2560x1440-60",
      RbFamily,
      2560,
      1440,
      60000,
      241500,
      true,
      "16:9",
      "CVT-RB 2560x1440@60",
    ),
    timing_entry(
      "rb-2560x1600-60",
      RbFamily,
      2560,
      1600,
      60000,
      268500,
      true,
      "16:10",
      "CVT-RB 2560x1600@60",
    ),
    timing_entry(
      "rb-3440x1440-60",
      RbFamily,
      3440,
      1440,
      60000,
      319750,
      true,
      "43:18",
      "CVT-RB 3440x1440@60",
    ),
    timing_entry(
      "rb-3840x2160-60",
      RbFamily,
      3840,
      2160,
      60000,
      533250,
      true,
      "16:9",
      "CVT-RB 3840x2160@60",
    ),
    timing_entry(
      "proj-1024x768-60",
      ProjectorFamily,
      1024,
      768,
      60000,
      65000,
      true,
      "4:3",
      "Projector XGA 1024x768@60",
    ),
    timing_entry(
      "proj-1280x800-60",
      ProjectorFamily,
      1280,
      800,
      60000,
      83500,
      true,
      "16:10",
      "Projector WXGA 1280x800@60",
    ),
    timing_entry(
      "proj-1920x1200-60",
      ProjectorFamily,
      1920,
      1200,
      60000,
      193250,
      true,
      "16:10",
      "Projector WUXGA 1920x1200@60",
    ),
  ]
}

///|
pub fn catalog_entries_by_family(
  family : TimingFamily,
) -> Array[TimingCatalogEntry] {
  let out : Array[TimingCatalogEntry] = []
  for entry in timing_catalog() {
    if entry.family == family {
      out.push(entry)
    }
  }
  out
}

///|
pub fn catalog_entries_by_resolution(
  width : Int,
  height : Int,
) -> Array[TimingCatalogEntry] {
  let out : Array[TimingCatalogEntry] = []
  for entry in timing_catalog() {
    if entry.width == width && entry.height == height {
      out.push(entry)
    }
  }
  out
}

///|
pub fn find_catalog_entry(id : String) -> TimingCatalogEntry? {
  for entry in timing_catalog() {
    if entry.id == id {
      return Some(entry)
    }
  }
  None
}

///|
pub fn catalog_match_for_mode(mode : DisplayMode) -> TimingCatalogEntry? {
  let mut best : TimingCatalogEntry? = None
  let mut best_score = 100000000
  for entry in timing_catalog() {
    let score = catalog_distance(entry, mode)
    if score < best_score {
      best_score = score
      best = Some(entry)
    }
  }
  if best_score <= 1200 {
    best
  } else {
    None
  }
}

///|
pub fn catalog_matches_for_edid(edid : Edid) -> Array[TimingCatalogEntry] {
  let out : Array[TimingCatalogEntry] = []
  for mode in modes_from_edid(edid) {
    match catalog_match_for_mode(mode) {
      Some(entry) => if !catalog_contains_id(out, entry.id) { out.push(entry) }
      None => ()
    }
  }
  out
}

///|
pub fn catalog_summary_for_edid(edid : Edid) -> String {
  let entries = catalog_matches_for_edid(edid)
  if entries.is_empty() {
    "catalog-matches=0"
  } else {
    let buf = StringBuilder(size_hint=entries.length() * 32)
    buf.write_string("catalog-matches=")
    buf.write_string(entries.length().to_string())
    for entry in entries {
      buf.write_string("; ")
      buf.write_string(entry.id)
    }
    buf.to_string()
  }
}

///|
pub fn catalog_to_markdown(entries : Array[TimingCatalogEntry]) -> String {
  let buf = StringBuilder(size_hint=entries.length() * 80 + 96)
  buf.write_string("| ID | Family | Mode | Clock kHz | Name |\n")
  buf.write_string("| --- | --- | --- | ---: | --- |")
  for entry in entries {
    buf.write_char('\n')
    buf.write_string("| ")
    buf.write_string(entry.id)
    buf.write_string(" | ")
    buf.write_string(entry.family.name())
    buf.write_string(" | ")
    buf.write_string(entry.label())
    buf.write_string(" | ")
    buf.write_string(entry.pixel_clock_khz.to_string())
    buf.write_string(" | ")
    buf.write_string(entry.name)
    buf.write_string(" |")
  }
  buf.to_string()
}

///|
pub fn highest_catalog_mode() -> TimingCatalogEntry {
  let entries = timing_catalog()
  let mut best = entries[0]
  for entry in entries {
    if timing_catalog_score(entry) > timing_catalog_score(best) {
      best = entry
    }
  }
  best
}

///|
pub fn high_refresh_catalog_entries() -> Array[TimingCatalogEntry] {
  let out : Array[TimingCatalogEntry] = []
  for entry in timing_catalog() {
    if entry.is_high_refresh() {
      out.push(entry)
    }
  }
  out
}

///|
fn timing_entry(
  id : String,
  family : TimingFamily,
  width : Int,
  height : Int,
  refresh_millihz : Int,
  pixel_clock_khz : Int,
  progressive : Bool,
  aspect : String,
  name : String,
) -> TimingCatalogEntry {
  {
    id,
    family,
    width,
    height,
    refresh_millihz,
    pixel_clock_khz,
    progressive,
    aspect,
    name,
  }
}

///|
fn catalog_distance(entry : TimingCatalogEntry, mode : DisplayMode) -> Int {
  let dw = abs_int(entry.width - mode.width)
  let dh = abs_int(entry.height - mode.height)
  let dr = abs_int(entry.refresh_millihz - mode.refresh_millihz) / 100
  dw * 10 + dh * 10 + dr
}

///|
fn timing_catalog_score(entry : TimingCatalogEntry) -> Int {
  entry.pixel_count() + (entry.refresh_millihz + 500) / 1000 * 100
}

///|
fn catalog_contains_id(
  entries : Array[TimingCatalogEntry],
  id : String,
) -> Bool {
  for entry in entries {
    if entry.id == id {
      return true
    }
  }
  false
}

///|
fn abs_int(value : Int) -> Int {
  if value < 0 {
    0 - value
  } else {
    value
  }
}