{
    "For Loop (Collection)": {
        "prefix": [
            "for-each"
        ],
        "body": [
            "for(${1:item} in ${2:collection}.vals()) {",
            "\t$0",
            "};"
        ],
        "description": "for loop which iterates through a collection"
    },
    "For Loop (Range)": {
        "prefix": [
            "for-range"
        ],
        "body": [
            "for(${1:i} in Iter.range(0, ${2:count} - 1)) {",
            "\t$0",
            "};"
        ],
        "description": "for loop over a numeric range"
    },
    "Range (Inclusive)": {
        "prefix": [
            "iter-range"
        ],
        "body": [
            "Iter.range(${1:start}, ${2:endInclusive})"
        ],
        "description": "iterator over a range of values (including the upper bound)."
    },
    "Range (Exclusive)": {
        "prefix": [
            "iter-range-exclusive"
        ],
        "body": [
            "Iter.range(${1:start}, ${2:end} - 1)"
        ],
        "description": "iterator over a range of values (excluding the upper bound)."
    },
    "Type Declaration": {
        "prefix": [
            "type"
        ],
        "body": [
            "type ${1:Name} = ${2:declaration};",
            "$0"
        ],
        "description": "simple type declaration"
    },
    "Object Type": {
        "prefix": [
            "type-obj"
        ],
        "body": [
            "type ${1:Name} = {",
            "\t${2:attribute} : ${3:Type};",
            "};",
            "$0"
        ],
        "description": "object / record type block"
    },
    "Type Variant": {
        "prefix": [
            "type-variant"
        ],
        "body": [
            "type ${1:Name} = {",
            "\t#${2:tag};",
            "};",
            "$0"
        ],
        "description": "variant type block"
    },
    "Mutable Variable": {
        "prefix": [
            "var"
        ],
        "body": [
            "var ${1:name} = ${2:value};",
            "$0"
        ],
        "description": "declare a mutable variable"
    },
    "Immutable Variable": {
        "prefix": [
            "let"
        ],
        "body": [
            "let ${1:name} = ${2:value};",
            "$0"
        ],
        "description": "declare an immutable variable"
    },
    "Simple Function": {
        "prefix": [
            "func"
        ],
        "body": [
            "func ${1:name}(${2:arg} : ${5:Type}) : ${4:()} {",
            "\t$0",
            "};"
        ],
        "description": "simple function declaration"
    },
    "Public Actor Function": {
        "prefix": [
            "func-actor"
        ],
        "body": [
            "public func ${1:name}(${2:arg} : ${5:Type}) : async ${4:()} {",
            "\t$0",
            "};"
        ],
        "description": "public actor function declaration"
    },
    "Core Package Import": {
        "prefix": [
            "import-core"
        ],
        "body": [
            "import ${1:Module} \"mo:core/${1}\";",
            "$0"
        ]
    },
    "Canister Import": {
        "prefix": [
            "import-canister"
        ],
        "body": [
            "import ${1:Module} \"canister:${2}\";",
            "$0"
        ]
    },
    "Switch Statement": {
        "prefix": [
            "switch"
        ],
        "body": [
            "switch(${1:input}) {",
            "\tcase($2) { $0 };",
            "\tcase($3) { };",
            "};"
        ]
    },
    "Switch Statement (Option)": {
        "prefix": [
            "switch-option"
        ],
        "body": [
            "switch(${1:input}) {",
            "\tcase(?${2:value}) { $0 };",
            "\tcase(null) { };",
            "};"
        ]
    },
    "Switch Statement (Result)": {
        "prefix": [
            "switch-result"
        ],
        "body": [
            "switch(${1:input}) {",
            "\tcase(#ok(${2:value})) { $0 };",
            "\tcase(#err(${3:error})) { };",
            "};"
        ]
    },
    "Module": {
        "prefix": [
            "module"
        ],
        "body": [
            "module {",
            "\tpublic let ${1:value} = ${2:0};",
            "\t",
            "\tpublic func ${3:name}(${4:arg : Text}) : ${5:()} {",
            "\t\t$0",
            "\t};",
            "};"
        ]
    },
    "Actor": {
        "prefix": [
            "actor"
        ],
        "body": [
            "actor {",
            "\tstable var ${1:state} = ${2:0};",
            "\t",
            "\tpublic func ${3:name}(${4:arg : Text}) : async ${5:()} {",
            "\t\t$0",
            "\t};",
            "};"
        ]
    },
    "Actor Class": {
        "prefix": [
            "actor-class"
        ],
        "body": [
            "actor class ${1:Name}($2) = self {",
            "\tstable var ${3:state} = ${4:0};",
            "\t",
            "\tpublic func ${5:name}(${6:input : Text}) : async ${7:()} {",
            "\t\t$0",
            "\t};",
            "};"
        ]
    },
    "Class": {
        "prefix": [
            "class"
        ],
        "body": [
            "class ${1:Name}($2) = self {",
            "\tvar ${3:state} = ${4:0};",
            "\t",
            "\tpublic func ${5:name}(${6:input : Text}) : ${7:()} {",
            "\t\t$0",
            "\t};",
            "};"
        ]
    },
    "Record": {
        "prefix": [
            "record"
        ],
        "body": [
            "{",
            "\t${1:key} = ${2:value};",
            "}"
        ],
        "description": "record value (equivalent to an object in JS, dictionary in Python)"
    },
    "Do Block": {
        "prefix": [
            "do"
        ],
        "body": [
            "do {",
            "\t$0",
            "}"
        ]
    },
    "Anonymous Function": {
        "prefix": [
            "lambda"
        ],
        "body": [
            "func ($1) { $0 }"
        ],
        "description": "a lambda expression"
    },
    "Array Literal": {
        "prefix": [
            "array"
        ],
        "body": [
            "[$0]"
        ],
        "description": "an immutable array (values cannot be replaced)"
    },
    "Mutable Array Literal": {
        "prefix": [
            "array-mut"
        ],
        "body": [
            "[var $0]"
        ],
        "description": "a mutable array (values can be replaced)"
    },
    "New Array": {
        "prefix": [
            "array-new"
        ],
        "body": [
            "var ${1:array} = [];",
            "$0"
        ]
    },
    "New Hash Map": {
        "prefix": [
            "hash-map-new"
        ],
        "body": [
            "let ${1:map} = HashMap.HashMap<${2:Text}, ${3:Nat}>(0, ${2}.equal, ${2}.hash);",
            "$0"
        ]
    },
    "New Trie": {
        "prefix": [
            "trie-new"
        ],
        "body": [
            "var ${1:trie} = Trie.empty<${2:Text}, ${3:Nat}>();",
            "$0"
        ]
    },
    "New Trie Map": {
        "prefix": [
            "trie-map-new"
        ],
        "body": [
            "let ${1:map} = TrieMap.TrieMap<${2:Text}, ${3:Nat}>(0);",
            "$0"
        ]
    },
    "New RB Tree": {
        "prefix": [
            "rb-tree-new"
        ],
        "body": [
            "let ${1:map} = RBTree.RBTree<${2:Text}, ${3:Nat}>(${2}.compare);",
            "$0"
        ]
    },
    "New Trie Set": {
        "prefix": [
            "trie-set-new"
        ],
        "body": [
            "let ${1:set} = TrieSet.empty<${2:Text}>();",
            "$0"
        ]
    },
    "New Deque": {
        "prefix": [
            "deque-new"
        ],
        "body": [
            "let ${1:queue} = Deque.empty<${2:Text}>();",
            "$0"
        ]
    },
    "New List": {
        "prefix": [
            "list-new"
        ],
        "body": [
            "var ${1:list} = List.nil<${2:Text}>();",
            "$0"
        ]
    },
    "Sort Array": {
        "prefix": [
            "sort-array"
        ],
        "body": [
            "Array.sort<$1>(${2:array}, func (a : $1, b : $1) { ${3:#equal} })"
        ]
    },
    "Ok (Result)": {
        "prefix": [
            "ok"
        ],
        "body": [
            "#ok($0)"
        ]
    },
    "Error (Result)": {
        "prefix": [
            "err"
        ],
        "body": [
            "#err($0)"
        ]
    },
    "Debug Block": {
        "prefix": [
            "debug-block"
        ],
        "body": [
            "debug {",
            "\t$0",
            "};"
        ]
    },
    "Print": {
        "prefix": [
            "debug-print"
        ],
        "body": [
            "Debug.print(debug_show ($0));"
        ]
    },
    "Trap": {
        "prefix": [
            "debug-trap"
        ],
        "body": [
            "Debug.trap(\"$0\");"
        ]
    },
    "Set Timer": {
        "prefix": [
            "set-timer"
        ],
        "body": [
            "let ${1:id} = Timer.setTimer<system>(#seconds ${2:0}, func () : async () {",
            "\t$0",
            "});"
        ]
    },
    "Recurring Timer": {
        "prefix": [
            "recurring-timer"
        ],
        "body": [
            "let ${1:id} = Timer.recurringTimer<system>(#seconds ${2:0}, func () : async () {",
            "\t$0",
            "});"
        ]
    },
    "Cancel Timer": {
        "prefix": [
            "cancel-timer"
        ],
        "body": [
            "Timer.cancelTimer(${1:id});"
        ]
    },
    "Doc Comment": {
        "prefix": [
            "doc-comment"
        ],
        "body": [
            "/// ${1:Description}"
        ]
    },
    "Array to Blob": {
        "prefix": [
            "array-2-blob"
        ],
        "body": [
            "Blob.fromArray(${1:array})"
        ]
    },
    "Blob to Array": {
        "prefix": [
            "blob-2-array"
        ],
        "body": [
            "Blob.toArray(${1:blob})"
        ]
    },
    "Array to Buffer": {
        "prefix": [
            "array-2-buffer"
        ],
        "body": [
            "Buffer.fromArray(${1:array})"
        ]
    },
    "Buffer to Array": {
        "prefix": [
            "buffer-2-array"
        ],
        "body": [
            "Buffer.toArray(${1:buffer})"
        ]
    },
    "Principal to Text": {
        "prefix": [
            "principal-2-text"
        ],
        "body": [
            "Principal.toText(${1:principal})"
        ]
    },
    "Text to Principal": {
        "prefix": [
            "text-2-principal"
        ],
        "body": [
            "Principal.fromText(${1:text})"
        ]
    },
    "Actor to Principal": {
        "prefix": [
            "actor-2-principal"
        ],
        "body": [
            "Principal.fromActor(${1:actor})"
        ]
    },
    "Principal to Actor": {
        "prefix": [
            "principal-2-actor"
        ],
        "body": [
            "actor (Principal.toText(${1:principal})) : actor { ${2:method} : ${3:()} -> async ${4:()} }"
        ]
    },
    "Text to Actor": {
        "prefix": [
            "text-2-actor"
        ],
        "body": [
            "actor (${1:text}) : actor { ${2:method} : ${3:()} -> async ${4:()} }"
        ]
    },
    "Profiling Region": {
        "prefix": [
            "profiling-region"
        ],
        "body": [
            "stable let profiling = do {",
            "\tlet r = Region.new();",
            "\tignore Region.grow(r, 32);",
            "\tr",
            "};"
        ],
        "description": "include as the first line in an actor for stable memory region profiling"
    }
}
