import gleam/http/request
import gleam/httpc.{FailedToConnect, InvalidUtf8Response, ResponseTimeout}
import gleam/io
import gleam/list
import gleam/result
import gleam/string
import internal/config.{type Configuration}
import internal/converter
import internal/module
const base_uri: String = "https://api.iconify.design/"
type IconifyError {
HttpError(String, httpc.HttpError)
InvalidResponse(String)
ConversionError(String)
ModuleError(module.ModuleError)
}
pub fn add(icon: String, config: Configuration) -> Nil {
let #(set, name) =
string.split_once(icon, "/")
|> result.unwrap(#(config.iconset, icon))
let module = string.replace(config.module, "*", normalize(set))
let module = case string.ends_with(module, "/") {
False -> module
True -> module <> normalize(name)
}
let filename = config.root <> "src/" <> module <> ".gleam"
io.print("- " <> set <> "/" <> name <> ": ")
case do_add(set, name, filename) {
Ok(change) -> io.println(module.change_to_string(change))
Error(HttpError(url, InvalidUtf8Response)) ->
io.println("Invalid response from " <> url)
Error(HttpError(url, FailedToConnect(..))) ->
io.println("Failed to connect to " <> url)
Error(HttpError(url, ResponseTimeout)) -> io.println("Timeout from " <> url)
Error(InvalidResponse(url)) -> io.println("Invalid response from " <> url)
Error(ConversionError(_)) -> io.println("Couldn't convert SVG to lustre")
Error(ModuleError(error)) -> io.println(module.error_to_string(error))
}
}
fn do_add(
set: String,
name: String,
filename: String,
) -> Result(module.ModuleChange, IconifyError) {
download(set, name)
|> result.try(convert)
|> result.try(adjust(filename, name, _))
}
fn download(set: String, name: String) -> Result(String, IconifyError) {
let url = base_uri <> set <> "/" <> name <> ".svg"
let assert Ok(request) = request.to(url)
request
|> httpc.send()
|> result.map_error(HttpError(url, _))
|> result.try(fn(response) {
case response.status {
200 -> Ok(response.body)
_ -> Error(InvalidResponse(url))
}
})
}
fn convert(svg: String) -> Result(String, IconifyError) {
svg
|> converter.to_lustre
|> result.map_error(ConversionError)
}
fn adjust(
filename: String,
fn_name: String,
fn_body: String,
) -> Result(module.ModuleChange, IconifyError) {
module.adjust(filename, fn_name, fn_body)
|> result.map_error(ModuleError)
}
fn normalize(filename: String) -> String {
filename
|> string.lowercase()
|> string.split("")
|> list.map(fn(char) {
case char {
"a"
| "b"
| "c"
| "d"
| "e"
| "f"
| "g"
| "h"
| "i"
| "j"
| "k"
| "l"
| "m"
| "n"
| "o"
| "p"
| "q"
| "r"
| "s"
| "t"
| "u"
| "v"
| "w"
| "x"
| "y"
| "z" -> char
_ -> "_"
}
})
|> string.join("")
}