package appearances import ( "fmt" "eq2emu/internal/database" ) // Appearance represents a single appearance with ID, name, and client version requirements type Appearance struct { ID int32 `json:"id"` // Appearance ID Name string `json:"name"` // Appearance name MinClient int16 `json:"min_client"` // Minimum client version required db *database.Database `json:"-"` // Database connection isNew bool `json:"-"` // Whether this is a new appearance } // New creates a new appearance with the given database func New(db *database.Database) *Appearance { return &Appearance{ db: db, isNew: true, } } // NewWithData creates a new appearance with data func NewWithData(id int32, name string, minClientVersion int16, db *database.Database) *Appearance { return &Appearance{ ID: id, Name: name, MinClient: minClientVersion, db: db, isNew: true, } } // Load loads an appearance by ID from the database func Load(db *database.Database, id int32) (*Appearance, error) { appearance := &Appearance{ db: db, isNew: false, } query := `SELECT appearance_id, name, min_client_version FROM appearances WHERE appearance_id = ?` row := db.QueryRow(query, id) err := row.Scan(&appearance.ID, &appearance.Name, &appearance.MinClient) if err != nil { return nil, fmt.Errorf("failed to load appearance %d: %w", id, err) } return appearance, nil } // GetID returns the appearance ID (implements Identifiable interface) func (a *Appearance) GetID() int32 { return a.ID } // GetName returns the appearance name func (a *Appearance) GetName() string { return a.Name } // GetMinClientVersion returns the minimum client version required func (a *Appearance) GetMinClientVersion() int16 { return a.MinClient } // GetNameString returns the name as a string (alias for GetName for C++ compatibility) func (a *Appearance) GetNameString() string { return a.Name } // SetName sets the appearance name func (a *Appearance) SetName(name string) { a.Name = name } // SetMinClientVersion sets the minimum client version func (a *Appearance) SetMinClientVersion(version int16) { a.MinClient = version } // IsCompatibleWithClient returns true if the appearance is compatible with the given client version func (a *Appearance) IsCompatibleWithClient(clientVersion int16) bool { return clientVersion >= a.MinClient } // IsNew returns true if this is a new appearance not yet saved to database func (a *Appearance) IsNew() bool { return a.isNew } // Save saves the appearance to the database func (a *Appearance) Save() error { if a.db == nil { return fmt.Errorf("no database connection available") } if a.isNew { return a.insert() } return a.update() } // Delete removes the appearance from the database func (a *Appearance) Delete() error { if a.db == nil { return fmt.Errorf("no database connection available") } if a.isNew { return fmt.Errorf("cannot delete unsaved appearance") } query := `DELETE FROM appearances WHERE appearance_id = ?` _, err := a.db.Exec(query, a.ID) if err != nil { return fmt.Errorf("failed to delete appearance %d: %w", a.ID, err) } return nil } // Reload reloads the appearance data from the database func (a *Appearance) Reload() error { if a.db == nil { return fmt.Errorf("no database connection available") } if a.isNew { return fmt.Errorf("cannot reload unsaved appearance") } query := `SELECT name, min_client_version FROM appearances WHERE appearance_id = ?` row := a.db.QueryRow(query, a.ID) err := row.Scan(&a.Name, &a.MinClient) if err != nil { return fmt.Errorf("failed to reload appearance %d: %w", a.ID, err) } return nil } // Clone creates a copy of the appearance func (a *Appearance) Clone() *Appearance { return &Appearance{ ID: a.ID, Name: a.Name, MinClient: a.MinClient, db: a.db, isNew: true, // Clone is always new } } // insert inserts a new appearance into the database func (a *Appearance) insert() error { query := `INSERT INTO appearances (appearance_id, name, min_client_version) VALUES (?, ?, ?)` _, err := a.db.Exec(query, a.ID, a.Name, a.MinClient) if err != nil { return fmt.Errorf("failed to insert appearance: %w", err) } a.isNew = false return nil } // update updates an existing appearance in the database func (a *Appearance) update() error { query := `UPDATE appearances SET name = ?, min_client_version = ? WHERE appearance_id = ?` result, err := a.db.Exec(query, a.Name, a.MinClient, a.ID) if err != nil { return fmt.Errorf("failed to update appearance: %w", err) } rowsAffected, err := result.RowsAffected() if err != nil { return fmt.Errorf("failed to get rows affected: %w", err) } if rowsAffected == 0 { return fmt.Errorf("appearance %d not found for update", a.ID) } return nil }