Files
Zockerhoehle/Zockerhoehle/Utils/LibraryImport.swift

271 lines
9.4 KiB
Swift

//
// LibraryImport.swift
// Zockerhoehle
//
// Created by Julian-Steffen Müller on 20.11.19.
// Copyright © 2019 Julian-Steffen Müller. All rights reserved.
//
import Foundation
import UIKit
import CoreData
// MARK: - Library Import
class LibraryImport {
let CDContext : NSManagedObjectContext
init(context CDContext: NSManagedObjectContext = CDManager.shared.viewContext) {
self.CDContext = CDContext
}
static func backupName(from filename : String) -> String? {
if filename.hasPrefix("libExp_") && filename.hasSuffix(".json") {
var backupName = filename
backupName.removeFirst("libExp_".count)
backupName.removeLast(".json".count)
return backupName
}else{
return .none
}
}
func backupFiles() -> [String] {
do {
guard let documentDirectory = ICloudManager.backup_folder else { return [] }
let filesInDocumentsDir = try FileManager.default.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: .none, options: [])
let backupFiles = filesInDocumentsDir.filter{
$0.isFileURL
}.map {
$0.lastPathComponent
}.filter {
$0.hasPrefix("libExp_") && $0.hasSuffix(".json")
}.sorted(by: { $0 > $1 })
return backupFiles
}catch let error {
print(error)
print("LibraryImport::backupFiles - Error reading files from Document directory!")
}
return []
}
func resetDatabase(games : [Game], accessories : [Accessory], consoles : [Console], gameSeries: [GameSeries]) {
self.CDContext.performAndWait {
// let gamesFR = NSFetchRequest<Game>(entityName: "Game")
// let accessoriesFR = NSFetchRequest<Accessory>(entityName: "Accessory")
// let consoleFR = NSFetchRequest<Console>(entityName: "Console")
// let gameSeriesFR = NSFetchRequest<GameSeries>(entityName: "GameSeries")
//
// let games = try CDManager.shared.viewContext.fetch(gamesFR) as [NSManagedObject]
// let accessories = try CDManager.shared.viewContext.fetch(accessoriesFR) as [NSManagedObject]
// let consoles = try CDManager.shared.viewContext.fetch(consoleFR) as [NSManagedObject]
// let gameSeries = try CDManager.shared.viewContext.fetch(gameSeriesFR) as [NSManagedObject]
//
var core_data_objects : [NSManagedObject] = []
core_data_objects.append(contentsOf: games)
core_data_objects.append(contentsOf: accessories)
core_data_objects.append(contentsOf: consoles)
core_data_objects.append(contentsOf: gameSeries)
for cdObject in core_data_objects {
CDManager.shared.viewContext.delete(cdObject)
}
}
}
private func noneIfEmpty(_ str : String?) -> String? {
if str == "" { return .none }
return str
}
private func makeCDGame(from game: BHLGame, _ gameDict: inout [UUID : Game], _ cdConsole: Console) {
let cdGame = Game(context: self.CDContext)
gameDict[game.uuid] = cdGame
cdGame.name = game.name ?? "n/a"
cdGame.uuid = game.uuid
cdGame.inWishlist = game.inWishlist
cdGame.isFinished = game.isFinished
cdGame.finishedDate = game.finishedDate
cdGame.lentTo = game.lentTo
cdGame.cover_icloud_path = game.cover_icloud_path
cdGame.notes = noneIfEmpty(game.notes)
cdGame.pickupDescription = noneIfEmpty(game.pickupDescription)
cdGame.isDigital = game.isDigital
cdGame.playtime_h = game.playtime_h ?? 0
cdGame.playtime_min = game.playtime_min ?? 0
if let pickupDate = game.pickupDate, let date = Date.from(string: pickupDate) {
cdGame.pickupDate = date
}else{
print("Could not decode date '\(game.pickupDate)' for game '\(cdGame.name)'")
}
if let date = Date.from(string: game.releaseDate) {
cdGame.releaseDate = date
}else{
print("Could not decode date '\(game.releaseDate)' for game '\(cdGame.name)'")
}
cdConsole.addToGames(cdGame)
cdGame.console = cdConsole
print("Imported: \(cdGame.name) for \(cdConsole.name)")
}
private func makeCDAccessory(from accessory: BHLAccessory, _ accessoryDict: inout [UUID : Accessory], _ cdConsole: Console) {
let cdAccessory = Accessory(context: self.CDContext)
accessoryDict[accessory.uuid] = cdAccessory
cdAccessory.name = accessory.name
cdAccessory.uuid = accessory.uuid
cdAccessory.lentTo = accessory.lentTo
cdAccessory.color = accessory.color
cdAccessory.manufacturer = accessory.manufacturer
cdAccessory.inWishlist = accessory.inWishlist
cdConsole.addToAccessories(cdAccessory)
cdAccessory.console = cdConsole
}
private func makeCDConsole(from console : BHLConsole) -> Console {
let cdConsole = Console(context: self.CDContext)
cdConsole.name = console.name ?? "n/a"
cdConsole.uuid = console.uuid
cdConsole.manufacturer = console.manufacturer
cdConsole.shortName = console.shortName
cdConsole.logo_icloud_path = console.logo_icloud_path
cdConsole.releaseDate = console.releaseDate
return cdConsole
}
private func makeCDGameSeries(from gameSeries: BHLGameSeries, _ gameDict: inout [UUID : Game]) {
let cdGameSeries = GameSeries(context: self.CDContext)
cdGameSeries.name = gameSeries.name
cdGameSeries.cover_icloud_path = gameSeries.cover_icloud_path
for uuid in gameSeries.games {
if let game = gameDict[uuid] {
cdGameSeries.addToGames(game)
game.series = cdGameSeries
}
}
}
func importLIB(from filename: String) {
guard let file = ICloudManager.backup_folder?.appendingPathComponent(filename) else {
print("LibraryImport:importLIB Could not get icloud backup folder")
return
}
if file.isFileURL {
do {
let data = try Data(contentsOf: file)
importLIB(data: data)
}catch let error {
print("LibraryImport::importLIB::String - Cannot create data from file '\(error)'")
}
}
}
func importLIB(data : Data) {
do {
let library = try JSONDecoder().decode(BHLibrary.self, from: data)
var gameDict = [UUID:Game]()
var accessoryDict = [UUID:Accessory]()
for console in library.consoles {
let cdConsole = makeCDConsole(from: console)
print("CONSOLE: \(cdConsole.name) with \(console.games.count) games")
for uuid in console.games {
if let game = library.games.first(where: {$0.uuid == uuid}) {
makeCDGame(from: game, &gameDict, cdConsole)
}else{
print("LibraryImport::importLIB - Game with UUID '\(uuid)' not found")
}
}
for uuid in console.accessories {
if let accessory = library.accessories.first(where: {$0.uuid == uuid}) {
makeCDAccessory(from: accessory, &accessoryDict, cdConsole)
}else{
print("LibraryImport::importLIB - Accessory with UUID '\(uuid)' not found")
}
}
}
for gameSeries in library.gameSeries {
makeCDGameSeries(from: gameSeries, &gameDict)
}
}catch let error {
print("LibraryImport::importLIB::DATA - Error while importing! '\(error)'")
}
print("Import Successfull")
}
}
// MARK: - BHLLibrary Classes
struct BHLibrary : Decodable {
let games : [BHLGame]
let consoles : [BHLConsole]
let gameSeries : [BHLGameSeries]
let accessories : [BHLAccessory]
}
struct BHLGame : Decodable {
let uuid : UUID
let name : String?
let lentTo : String?
let isDigital : Bool
let inWishlist : Bool
let isFinished : Bool
let finishedDate : Date?
let notes : String?
let releaseDate : String
let pickupDate : String?
let pickupDescription : String?
let publisher : String?
let console : UUID
let cover_icloud_path : String?
let playtime_h : Int?
let playtime_min : Int?
}
struct BHLAccessory : Decodable {
let uuid : UUID
let name : String
let color : String?
let manufacturer : String?
let inWishlist : Bool
let lentTo : String?
let console : UUID?
}
struct BHLGameSeries : Decodable {
let uuid : UUID
let name : String
let games : [UUID]
let cover_icloud_path : String?
}
struct BHLConsole : Decodable {
let uuid : UUID
let name : String?
let logo_icloud_path : String?
let manufacturer : String?
let releaseDate : Date
let shortName : String?
let accessories : [UUID]
let games : [UUID]
}