// // TileImage.swift // CapCollector // // Created by Christoph on 20.05.20. // Copyright © 2020 CH. All rights reserved. // import Foundation import SQLite extension Database { struct TileImage { let name: String let width: Int /// The tiles of each cap, with the index being the tile, and the value being the cap id. let caps: [Int] var encodedCaps: Data { caps.map(UInt16.init).withUnsafeBytes { (p) in Data(buffer: p.bindMemory(to: UInt8.self)) } } init(name: String, width: Int, caps: [Int]) { self.name = name self.width = width self.caps = caps } init(row: Row) { self.name = row[TileImage.columnName] self.width = row[TileImage.columnWidth] self.caps = row[TileImage.columnCaps].withUnsafeBytes { p in p.bindMemory(to: UInt16.self).map(Int.init) } } var insertQuery: Insert { TileImage.table.insert( TileImage.columnName <- name, TileImage.columnWidth <- width, TileImage.columnCaps <- encodedCaps) } var updateQuery: Update { TileImage.table.update( TileImage.columnWidth <- width, TileImage.columnCaps <- encodedCaps) } static let columnName = Expression("name") static let columnWidth = Expression("width") static let columnCaps = Expression("caps") static let table = Table("images") static func named(_ name: String) -> Table { table.filter(columnName == name) } static func exists(_ name: String) -> Table { named(name).select(columnName) } static var createQuery: String { table.create(ifNotExists: true) { t in t.column(Cap.columnId, primaryKey: true) t.column(columnName) t.column(columnWidth) t.column(columnCaps) } } } func save(tileImage: TileImage) -> Bool { guard exists(tileImage.name) else { return insert(tileImage) } return update(tileImage) } var tileImages: [TileImage] { (try? db.prepare(TileImage.table).map(TileImage.init)) ?? [] } func tileImage(named name: String) -> TileImage? { do { guard let row = try db.pluck(TileImage.named(name)) else { return nil } return TileImage(row: row) } catch { log("Failed to get tile image \(name): \(error)") return nil } } private func exists(_ tileImage: String) -> Bool { do { return try db.pluck(TileImage.exists(tileImage)) != nil } catch { log("Failed to check tile image \(tileImage): \(error)") return false } } private func insert(_ tileImage: TileImage) -> Bool { do { try db.run(tileImage.insertQuery) return true } catch { log("Failed to insert tile image \(tileImage): \(error)") return false } } private func update(_ tileImage: TileImage) -> Bool { do { try db.run(tileImage.updateQuery) return true } catch { log("Failed to update tile image \(tileImage): \(error)") return false } } }