//// Syntax test file for Gleam
////
//// This is a dummy example file and should not be taken as a reference of
//// well written Gleam, but it does compile correctly appart from an error
//// for the absent file "./ffi.mjs" and some warnings.
////
////
////
//// ## Top module documentation comment with markdown formatting
////
//// Formats: _italic text_, **bold text**, `monospace text`, ~~strikeout~~
////
//// Bullet list:
////
//// - item 1
//// - item 2
////
//// Numbered list:
////
//// 1. item 1
//// 2. item 2
////
//// [link](https://example.com)

// SPDX-FileCopyrightText: 2024 Louis Guichard <kde@glpda.net>
// SPDX-License-Identifier: MIT

import gleam/bit_array as bit_string
import gleam/bool
import gleam/dict<beginfold id='1'>.{</beginfold id='1'>type Dict, delete, get, insert<endfold id='1'>}</endfold id='1'>
import gleam/io

// <beginfold id='2'>BEGIN</beginfold id='2'>

pub fn main<beginfold id='3'>(</beginfold id='3'><endfold id='3'>)</endfold id='3'> <beginfold id='1'>{</beginfold id='1'>
  let assert Ok<beginfold id='3'>(</beginfold id='3'>prefix<endfold id='3'>)</endfold id='3'> = bit_string.to_string<beginfold id='3'>(</beginfold id='3'>prefix<endfold id='3'>)</endfold id='3'>
  let name: String = <beginfold id='4'>"</beginfold id='4'>Kate \u{1F3F3}\u{FE0F}\u{200D}\u{1F308} <endfold id='4'>"</endfold id='4'>
  let assert Ok<beginfold id='3'>(</beginfold id='3'>suffix<endfold id='3'>)</endfold id='3'> = get<beginfold id='3'>(</beginfold id='3'>mascots<beginfold id='3'>(</beginfold id='3'><endfold id='3'>)</endfold id='3'>, <beginfold id='4'>"</beginfold id='4'>Lucy<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
  echo prefix <> name <> suffix
<endfold id='1'>}</endfold id='1'>

const prefix = <beginfold id='5'><<</beginfold id='5'><beginfold id='4'>"</beginfold id='4'>Hello<endfold id='4'>"</endfold id='4'>:utf8, 44:size<beginfold id='3'>(</beginfold id='3'>8<endfold id='3'>)</endfold id='3'>, 32:int<endfold id='5'>>></endfold id='5'>

fn number<beginfold id='3'>(</beginfold id='3'>int<endfold id='3'>)</endfold id='3'> <beginfold id='1'>{</beginfold id='1'>
  use <- bool.guard<beginfold id='3'>(</beginfold id='3'>when: int < 0, return: False<endfold id='3'>)</endfold id='3'>
  let dec = 123_456_789
  let bin = 0b10011011
  let oct = 0o1234567
  let hex = 0x8337_BEEF
  let _float = -3.1415 *. 1.0e-4
  let roof = <beginfold id='1'>{</beginfold id='1'> <beginfold id='1'>{</beginfold id='1'> dec + oct <endfold id='1'>}</endfold id='1'> * bin - hex <endfold id='1'>}</endfold id='1'> / 4
  // 4_246_851_061
  case int <beginfold id='1'>{</beginfold id='1'>
    _ if int < roof -> True
    _ -> False
  <endfold id='1'>}</endfold id='1'>
<endfold id='1'>}</endfold id='1'>

/// Documentation for a custom type with 3 variants
pub opaque type CustomType<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'> <beginfold id='1'>{</beginfold id='1'>
  /// first variant
  Var1<beginfold id='3'>(</beginfold id='3'>x: a<endfold id='3'>)</endfold id='3'>

  /// second variant
  Var2<beginfold id='3'>(</beginfold id='3'>x: a, y: a<endfold id='3'>)</endfold id='3'>

  /// third variant
  Var3<beginfold id='3'>(</beginfold id='3'>x: a, y: a, z: a<endfold id='3'>)</endfold id='3'>
<endfold id='1'>}</endfold id='1'>

pub fn first<beginfold id='3'>(</beginfold id='3'>ct: CustomType<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'> -> a <beginfold id='1'>{</beginfold id='1'>
  ct.x
<endfold id='1'>}</endfold id='1'>

@deprecated<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Use last instead<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
pub fn third<beginfold id='3'>(</beginfold id='3'>ct: CustomType<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'> -> a <beginfold id='1'>{</beginfold id='1'>
  // let assert Var3(_, _, z) = ct  z
  case ct <beginfold id='1'>{</beginfold id='1'>
    Var3<beginfold id='3'>(</beginfold id='3'>_, _, z<endfold id='3'>)</endfold id='3'> -> z
    _ -> panic
  <endfold id='1'>}</endfold id='1'>
<endfold id='1'>}</endfold id='1'>

pub fn last<beginfold id='3'>(</beginfold id='3'>ct: CustomType<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'> -> a <beginfold id='1'>{</beginfold id='1'>
  case ct <beginfold id='1'>{</beginfold id='1'>
    Var1<beginfold id='3'>(</beginfold id='3'>x<endfold id='3'>)</endfold id='3'> -> x
    Var2<beginfold id='3'>(</beginfold id='3'>_, y<endfold id='3'>)</endfold id='3'> -> y
    Var3<beginfold id='3'>(</beginfold id='3'>_, _, z<endfold id='3'>)</endfold id='3'> -> z
  <endfold id='1'>}</endfold id='1'>
<endfold id='1'>}</endfold id='1'>

pub type ListError <beginfold id='1'>{</beginfold id='1'>
  EmptyList
  ListTooLong
<endfold id='1'>}</endfold id='1'>

/// Converts a `List(a)` to a `Result(CustomType(a))`, empty list and list
/// longer than 3 will return an error.
///
/// ## Examples
///
/// ```gleam
/// from_list([1, 2, 3])
/// // -> Ok(Var3(1, 2, 3))
///
/// from_list([1, 2, 3, 4, 5])
/// // -> Error(ListTooLong)
/// ```
///
pub fn from_list<beginfold id='3'>(</beginfold id='3'>l: List<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'> -> Result<beginfold id='3'>(</beginfold id='3'>CustomType<beginfold id='3'>(</beginfold id='3'>a<endfold id='3'>)</endfold id='3'>, ListError<endfold id='3'>)</endfold id='3'> <beginfold id='1'>{</beginfold id='1'>
  case l <beginfold id='1'>{</beginfold id='1'>
    <beginfold id='6'>[</beginfold id='6'>x<endfold id='6'>]</endfold id='6'> -> Ok<beginfold id='3'>(</beginfold id='3'>Var1<beginfold id='3'>(</beginfold id='3'>x<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'>
    <beginfold id='6'>[</beginfold id='6'>x, y<endfold id='6'>]</endfold id='6'> -> Ok<beginfold id='3'>(</beginfold id='3'>Var2<beginfold id='3'>(</beginfold id='3'>x, y<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'>
    <beginfold id='6'>[</beginfold id='6'>x, y, z<endfold id='6'>]</endfold id='6'> -> Ok<beginfold id='3'>(</beginfold id='3'>Var3<beginfold id='3'>(</beginfold id='3'>x, y, z<endfold id='3'>)</endfold id='3'><endfold id='3'>)</endfold id='3'>
    <beginfold id='6'>[</beginfold id='6'><endfold id='6'>]</endfold id='6'> -> Error<beginfold id='3'>(</beginfold id='3'>EmptyList<endfold id='3'>)</endfold id='3'>
    _ -> Error<beginfold id='3'>(</beginfold id='3'>ListTooLong<endfold id='3'>)</endfold id='3'>
  <endfold id='1'>}</endfold id='1'>
<endfold id='1'>}</endfold id='1'>

fn mascots<beginfold id='3'>(</beginfold id='3'><endfold id='3'>)</endfold id='3'> -> Dict<beginfold id='3'>(</beginfold id='3'>String, String<endfold id='3'>)</endfold id='3'> <beginfold id='1'>{</beginfold id='1'>
  let old_mascots = dict.from_list<beginfold id='3'>(</beginfold id='3'><beginfold id='6'>[</beginfold id='6'>#<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Konqi<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>🐉<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>, #<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Kandalf<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>🧙<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'><endfold id='6'>]</endfold id='6'><endfold id='3'>)</endfold id='3'>
  let new_mascots =
    old_mascots
    |> delete<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Kandalf<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
    |> insert<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Kate<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>🐦<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
    |> insert<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Katie<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>🐉<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
    |> insert<beginfold id='3'>(</beginfold id='3'><beginfold id='4'>"</beginfold id='4'>Lucy<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>🌟<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
  new_mascots
<endfold id='1'>}</endfold id='1'>

type UserId =
  Int

@external<beginfold id='3'>(</beginfold id='3'>javascript, <beginfold id='4'>"</beginfold id='4'>./ffi.mjs<endfold id='4'>"</endfold id='4'>, <beginfold id='4'>"</beginfold id='4'>call<endfold id='4'>"</endfold id='4'><endfold id='3'>)</endfold id='3'>
fn call<beginfold id='3'>(</beginfold id='3'>id: UserId<endfold id='3'>)</endfold id='3'> -> String <beginfold id='1'>{</beginfold id='1'>
  todo as <beginfold id='4'>"</beginfold id='4'>call not implemented for this target<endfold id='4'>"</endfold id='4'>
<endfold id='1'>}</endfold id='1'>
// <endfold id='2'>END</endfold id='2'>
