// Copyright (c) 2024 Synty Studios Limited. All rights reserved.
//
// Use of this software is subject to the terms and conditions of the Synty Studios End User Licence Agreement (EULA)
// available at: https://syntystore.com/pages/end-user-licence-agreement
//
// For additional details, see the LICENSE.MD file bundled with this software.
using SQLite;
using Synty.SidekickCharacters.Enums;
using Synty.SidekickCharacters.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Synty.SidekickCharacters.Database.DTO
{
[Table("sk_part_preset")]
public class SidekickPartPreset
{
private SidekickSpecies _species;
[PrimaryKey]
[AutoIncrement]
[Column("id")]
public int ID { get; set; }
[Column("name")]
public string Name { get; set; }
[Column("part_group")]
public PartGroup PartGroup { get; set; }
[Column("ptr_species")]
public int PtrSpecies { get; set; }
[Column("outfit")]
public string Outfit { get; set; }
[Ignore]
public SidekickSpecies Species
{
get => _species;
set
{
_species = value;
PtrSpecies = value.ID;
}
}
///
/// Gets a specific Preset by its database ID.
///
/// The Database Manager to use.
/// The id of the required Preset.
/// The specific Preset if it exists; otherwise null.
public static SidekickPartPreset GetByID(DatabaseManager dbManager, int id)
{
SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection().Find(id);
Decorate(dbManager, partPreset);
return partPreset;
}
///
/// Gets a list of all the Presets in the database.
///
/// The Database Manager to use.
/// A list of all presets in the database.
public static List GetAll(DatabaseManager dbManager)
{
List partPresets = dbManager.GetCurrentDbConnection().Table().ToList();
foreach (SidekickPartPreset partPreset in partPresets)
{
Decorate(dbManager, partPreset);
}
return partPresets;
}
///
/// Gets a list of all the Part Presets in the database that have the matching species.
///
/// The Database Manager to use.
/// The species to get all the part presets for.
/// A list of all part presets in the database for the given species.
public static List GetAllBySpecies(DatabaseManager dbManager, SidekickSpecies species)
{
List partPresets = dbManager.GetCurrentDbConnection().Table()
.Where(partPreset => partPreset.PtrSpecies == species.ID)
.ToList();
foreach (SidekickPartPreset partPreset in partPresets)
{
partPreset.Species = species;
}
return partPresets;
}
///
/// Gets a Part Presets in the database with the matching name if one exists.
///
/// The Database Manager to use.
/// The name of the preset to retrieve.
/// Returns a Part Presets in the database with the matching name if one exists; otherwise null.
public static SidekickPartPreset GetByName(DatabaseManager dbManager, string name)
{
SidekickPartPreset partPreset = dbManager.GetCurrentDbConnection()
.Table()
.FirstOrDefault(partPreset => partPreset.Name == name);
if (partPreset != null)
{
Decorate(dbManager, partPreset);
}
return partPreset;
}
///
/// Gets a list of all the Part Presets in the database that have the matching species and part group.
///
/// The Database Manager to use.
/// The part group to filter search by.
/// A list of all part presets in the database for the given species and part group.
public static List GetAllByGroup(DatabaseManager dbManager, PartGroup partGroup, bool excludeMissingParts = true)
{
List partPresets = dbManager.GetCurrentDbConnection().Table()
.Where(partPreset => partPreset.PartGroup == partGroup)
.ToList();
foreach (SidekickPartPreset partPreset in partPresets)
{
Decorate(dbManager, partPreset);
}
if (excludeMissingParts)
{
List toRemove = new List();
foreach (SidekickPartPreset partPreset in partPresets)
{
if (!partPreset.HasAllPartsAvailable(dbManager))
{
toRemove.Add(partPreset);
}
}
partPresets.RemoveAll(preset => toRemove.Contains(preset));
}
return partPresets;
}
///
/// Gets a list of all the Part Presets in the database that have the matching species and part group.
///
/// The Database Manager to use.
/// The species to get all the part presets for.
/// The part group to filter search by.
/// A list of all part presets in the database for the given species and part group.
public static List GetAllBySpeciesAndGroup(DatabaseManager dbManager, SidekickSpecies species, PartGroup partGroup)
{
List partPresets = dbManager.GetCurrentDbConnection().Table()
.Where(partPreset => partPreset.PtrSpecies == species.ID && partPreset.PartGroup == partGroup)
.ToList();
foreach (SidekickPartPreset partPreset in partPresets)
{
partPreset.Species = species;
}
return partPresets;
}
///
/// Ensures that the given set has its nice DTO class properties set
///
/// The Database Manager to use.
/// The color set to decorate
/// A color set with all DTO class properties set
private static void Decorate(DatabaseManager dbManager, SidekickPartPreset partPreset)
{
if (partPreset.Species == null && partPreset.PtrSpecies >= 0)
{
partPreset.Species = SidekickSpecies.GetByID(dbManager, partPreset.PtrSpecies);
}
}
///
/// Updates or Inserts this item in the Database.
///
/// The database manager to use.
public int Save(DatabaseManager dbManager)
{
if (ID < 0)
{
dbManager.GetCurrentDbConnection().Insert(this);
// in theory this could return a different ID, but in practice it's highly unlikely
ID = (int) SQLite3.LastInsertRowid(dbManager.GetCurrentDbConnection().Handle);
}
dbManager.GetCurrentDbConnection().Update(this);
return ID;
}
///
/// Deletes this item from the database
///
/// The database manager to use.
public void Delete(DatabaseManager dbManager)
{
foreach (SidekickPartPresetRow row in SidekickPartPresetRow.GetAllByPreset(dbManager, this))
{
row.Delete(dbManager);
}
foreach (SidekickPresetFilterRow row in SidekickPresetFilterRow.GetAllForPreset(dbManager, this))
{
row.Delete(dbManager);
}
SidekickPartPresetImage image = SidekickPartPresetImage.GetByPresetAndPartGroup(dbManager, this, PartGroup);
image?.Delete(dbManager);
dbManager.GetCurrentDbConnection().Delete(ID);
}
///
/// Determines if all the parts associated with this preset are valid (has a file in the project).
///
/// The database manager to use.
/// True if all parts are valid; otherwise False.
public bool HasAllPartsAvailable(DatabaseManager dbManager)
{
List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this);
return allRows.Count > 0 && allRows.All(row => row.HasValidPart());
}
///
/// Determines if all the parts associated with this preset are valid (has a file in the project).
///
/// The database manager to use.
/// True if all parts are valid; otherwise False.
public bool HasOnlyBasePartsAndAllAvailable(DatabaseManager dbManager)
{
List allRows = SidekickPartPresetRow.GetAllByPreset(dbManager, this);
return allRows.Count > 0 && allRows.All(row => row.HasValidPart() && (row.Part == null || PartUtils.IsBaseSpeciesPart(row.PartName)));
}
///
/// Checks the equality of this preset to the given preset.
///
/// The preset to check equality with.
/// True if the presets are equal, otherwise false.
protected bool Equals(SidekickPartPreset other)
{
return ID == other.ID
&& Name == other.Name
&& PartGroup == other.PartGroup
&& PtrSpecies == other.PtrSpecies;
}
///
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != this.GetType())
{
return false;
}
return Equals((SidekickPartPreset) obj);
}
///
public override int GetHashCode()
{
return HashCode.Combine(ID, Name, (int) PartGroup, PtrSpecies);
}
}
}