// // CookbookApiV1.swift // Nextcloud Cookbook iOS Client // // Created by Vincent Meilinger on 16.11.23. // import Foundation import UIKit class CookbookApiV1: CookbookApi { static let basePath: String = "/index.php/apps/cookbook/api/v1" static func importRecipe(auth: String, data: Data) async -> (Recipe?, NetworkError?) { let request = ApiRequest( path: basePath + "/import", method: .POST, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON), HeaderField.contentType(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } let recipe: CookbookApiRecipeDetailV1? = JSONDecoder.safeDecode(data) return (recipe?.toRecipe(), error) } static func getImage(auth: String, id: String, size: RecipeImage.RecipeImageSize) async -> (UIImage?, NetworkError?) { guard let id = Int(id) else {return (nil, .unknownError)} let imageSize = (size == .FULL ? "full" : "thumb") let request = ApiRequest( path: basePath + "/recipes/\(id)/image?size=\(imageSize)", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .IMAGE)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } return (UIImage(data: data), error) } static func getRecipes(auth: String) async -> ([RecipeStub]?, NetworkError?) { let request = ApiRequest( path: basePath + "/recipes", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } print("\n\nRECIPE: ", String(data: data, encoding: .utf8)) let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data) return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil) } static func createRecipe(auth: String, recipe: Recipe) async -> (NetworkError?) { let recipe = CookbookApiRecipeDetailV1.fromRecipe(recipe) guard let recipeData = JSONEncoder.safeEncode(recipe) else { return .dataError } let request = ApiRequest( path: basePath + "/recipes", method: .POST, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON), HeaderField.contentType(value: .JSON)], body: recipeData ) let (data, error) = await request.send() guard let data = data else { return (error) } do { let json = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) if let id = json as? Int { return nil } else if let dict = json as? [String: Any] { return .serverError } } catch { return .decodingFailed } return nil } static func getRecipe(auth: String, id: String) async -> (Recipe?, NetworkError?) { guard let id = Int(id) else {return (nil, .unknownError)} let request = ApiRequest( path: basePath + "/recipes/\(id)", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } let recipe: CookbookApiRecipeDetailV1? = JSONDecoder.safeDecode(data) return (recipe?.toRecipe(), nil) } static func updateRecipe(auth: String, recipe: Recipe) async -> (NetworkError?) { let cookbookRecipe = CookbookApiRecipeDetailV1.fromRecipe(recipe) guard let recipeData = JSONEncoder.safeEncode(recipe) else { return .dataError } let request = ApiRequest( path: basePath + "/recipes/\(recipe.id)", method: .PUT, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON), HeaderField.contentType(value: .JSON)], body: recipeData ) let (data, error) = await request.send() guard let data = data else { return (error) } do { let json = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) if let id = json as? Int { return nil } else if let dict = json as? [String: Any] { return .serverError } } catch { return .decodingFailed } return nil } static func deleteRecipe(auth: String, id: String) async -> (NetworkError?) { guard let id = Int(id) else {return .unknownError} let request = ApiRequest( path: basePath + "/recipes/\(id)", method: .DELETE, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (error) } return nil } static func getCategories(auth: String) async -> ([Category]?, NetworkError?) { let request = ApiRequest( path: basePath + "/categories", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } return (JSONDecoder.safeDecode(data), nil) } static func getCategory(auth: String, named categoryName: String) async -> ([RecipeStub]?, NetworkError?) { let request = ApiRequest( path: basePath + "/category/\(categoryName)", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data) return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil) } static func renameCategory(auth: String, named categoryName: String, newName: String) async -> (NetworkError?) { let request = ApiRequest( path: basePath + "/category/\(categoryName)", method: .PUT, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (error) } return nil } static func getTags(auth: String) async -> ([RecipeKeyword]?, NetworkError?) { let request = ApiRequest( path: basePath + "/keywords", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } return (JSONDecoder.safeDecode(data), nil) } static func getRecipesTagged(auth: String, keyword: String) async -> ([RecipeStub]?, NetworkError?) { let request = ApiRequest( path: basePath + "/tags/\(keyword)", method: .GET, authString: auth, headerFields: [HeaderField.ocsRequest(value: true), HeaderField.accept(value: .JSON)] ) let (data, error) = await request.send() guard let data = data else { return (nil, error) } let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data) return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil) } static func getApiVersion(auth: String) async -> (NetworkError?) { return .none } static func postReindex(auth: String) async -> (NetworkError?) { return .none } static func getConfig(auth: String) async -> (NetworkError?) { return .none } static func postConfig(auth: String) async -> (NetworkError?) { return .none } }