157 lines
5.2 KiB
Swift
157 lines
5.2 KiB
Swift
//
|
|
// BudgetApiService.swift
|
|
// Budget
|
|
//
|
|
// Created by Billy Brawner on 9/25/19.
|
|
// Copyright © 2019 William Brawner. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Foundation
|
|
import TwigsCore
|
|
|
|
class TwigsInMemoryCacheService: TwigsApiService {
|
|
private var budgets = Set<Budget>()
|
|
private var categories = Set<TwigsCore.Category>()
|
|
private var transactions = Set<TwigsCore.Transaction>()
|
|
|
|
|
|
public init() {
|
|
super.init(RequestHelper())
|
|
}
|
|
|
|
// MARK: Budgets
|
|
override func getBudgets(count: Int? = nil, page: Int? = nil) async throws -> [Budget] {
|
|
let results = budgets.sorted { (first, second) -> Bool in
|
|
return first.name < second.name
|
|
}
|
|
if results.isEmpty {
|
|
let budgets = try await super.getBudgets(count: count, page: page)
|
|
self.addBudgets(budgets)
|
|
return budgets
|
|
}
|
|
return results.slice(count: count, page: page)
|
|
}
|
|
|
|
override func getBudget(_ id: String) async throws -> Budget {
|
|
guard let budget = budgets.first(where: { $0.id == id }) else {
|
|
let budget = try await super.getBudget(id)
|
|
self.addBudget(budget)
|
|
return budget
|
|
}
|
|
return budget
|
|
}
|
|
|
|
override func newBudget(_ budget: Budget) async throws -> Budget {
|
|
let newBudget = try await super.newBudget(budget)
|
|
self.addBudget(newBudget)
|
|
return newBudget
|
|
}
|
|
|
|
override func updateBudget(_ budget: Budget) async throws -> Budget {
|
|
let newBudget = try await super.updateBudget(budget)
|
|
if let index = self.budgets.firstIndex(where: {$0.id == budget.id}) {
|
|
self.budgets.remove(at: index)
|
|
}
|
|
self.addBudget(newBudget)
|
|
return newBudget
|
|
}
|
|
|
|
override func deleteBudget(_ id: String) async throws {
|
|
try await super.deleteBudget(id)
|
|
if let index = self.budgets.firstIndex(where: {$0.id == id}) {
|
|
self.budgets.remove(at: index)
|
|
}
|
|
}
|
|
|
|
private func addBudgets(_ budgets: [Budget]) {
|
|
budgets.forEach { addBudget($0) }
|
|
}
|
|
|
|
private func addBudget(_ budget: Budget) {
|
|
self.budgets.insert(budget)
|
|
}
|
|
|
|
// MARK: Categories
|
|
override func getCategories(budgetId: String? = nil, expense: Bool? = nil, archived: Bool? = nil, count: Int? = nil, page: Int? = nil) async throws -> [TwigsCore.Category] {
|
|
var results = categories
|
|
if budgetId != nil {
|
|
results = categories.filter { $0.budgetId == budgetId }
|
|
}
|
|
if expense != nil {
|
|
results = results.filter { $0.expense == expense }
|
|
}
|
|
if archived != nil {
|
|
results = results.filter { $0.archived == archived }
|
|
}
|
|
if results.isEmpty {
|
|
let categories = try await super.getCategories(budgetId: budgetId, expense: expense, archived: archived, count: count, page: page)
|
|
self.addCategories(categories)
|
|
return categories
|
|
}
|
|
let sortedResults = results.sorted { $0.title < $1.title }
|
|
return sortedResults.slice(count: count, page: page)
|
|
}
|
|
|
|
override func getCategory(_ id: String) async throws -> TwigsCore.Category {
|
|
guard let category = categories.first(where: { $0.id == id }) else {
|
|
let category = try await super.getCategory(id)
|
|
self.addCategory(category)
|
|
return category
|
|
}
|
|
return category
|
|
}
|
|
|
|
private func addCategories(_ categories: [TwigsCore.Category]) {
|
|
categories.forEach { addCategory($0) }
|
|
}
|
|
|
|
private func addCategory(_ category: TwigsCore.Category) {
|
|
self.categories.insert(category)
|
|
}
|
|
|
|
override func createCategory(_ category: TwigsCore.Category) async throws -> TwigsCore.Category {
|
|
let newCategory = try await super.createCategory(category)
|
|
self.categories.insert(newCategory)
|
|
return newCategory
|
|
}
|
|
|
|
override func updateCategory(_ category: TwigsCore.Category) async throws -> TwigsCore.Category {
|
|
let newCategory = try await super.updateCategory(category)
|
|
self.removeCategory(newCategory.id)
|
|
self.categories.insert(newCategory)
|
|
return newCategory
|
|
}
|
|
|
|
override func deleteCategory(_ id: String) async throws {
|
|
try await super.deleteCategory(id)
|
|
self.removeCategory(id)
|
|
}
|
|
|
|
private func removeCategory(_ id: String) {
|
|
if let index = self.categories.firstIndex(where: { $0.id == id }) {
|
|
self.categories.remove(at: index)
|
|
}
|
|
}
|
|
}
|
|
|
|
extension TwigsApiService: ObservableObject {}
|
|
|
|
/**
|
|
* Determines which slice of the array should be returned based on the count and page parameters
|
|
*/
|
|
private func calculateStartAndEndIndices(count: Int, page: Int?) -> (start: Int, end: Int?) {
|
|
let end = count * (page ?? 1)
|
|
let start = max(end - count, 0)
|
|
return (start, end)
|
|
}
|
|
|
|
extension Array {
|
|
func slice(count: Int?, page: Int?) -> Array<Element> {
|
|
if count == nil {
|
|
return self
|
|
}
|
|
let indices: (Int, Int?) = calculateStartAndEndIndices(count: count!, page: page)
|
|
return Array(self[indices.0..<Swift.min((indices.1 ?? self.count), self.count)])
|
|
}
|
|
}
|