Source: classes/books/Book.js

/** @module classes */

const BookController = require('../../controllers/BookController.js');
const AuthorController = require('../../controllers/AuthorController.js');
const EditionController = require('../../controllers/EditionController.js');
const BaseFactory = require('../Base.js');

/** Class representing a Book. */
class Book {
    /**
     * Create a book.
     * @param {number} id
     * @param {string} title
     * @param {Date} publicationDate
     * @param {Date} createdAt
     * @param {Date} updatedAt
     * @param {string} subtitle
     */
    constructor(id, title, publicationDate, createdAt, updatedAt, subtitle = null) {
        this.id = id;
        this.title = title;
        this.subtitle = subtitle;
        this.publicationDate = publicationDate;
        this.createdAt = createdAt;
        this.updatedAt = updatedAt;
    }

    /**
     * Get the authors of the book.
     * 
     * @param {bool} forceRefresh
     * @returns {Promise<object[]>}
     */
    async getAuthors(forceRefresh = false) {
        if (this.authors && !forceRefresh) {
            return this.authors;
        }

        this.authors = await new AuthorController().byBook(this.id);

        return this.authors;
    }

    /**
     * Get the editions of the book.
     * 
     * @param {bool} forceRefresh
     * @returns {Promise<object[]>}
     */
    async getEditions(forceRefresh = false) {
        if (this.editions && !forceRefresh) {
            return this.editions;
        }

        this.editions = await new EditionController().byBook(this);

        return this.editions;
    }

    /** Refreshes data from the database that has been pulled at least once before in this instance. */
    async refresh() {
        if (this.authors) {
            await this.getAuthors(true);
        }

        if (this.editions) {
            await this.getEditions(true);
        }
    }
}

/** Class representing a book factory. */
class BookFactory extends BaseFactory {
    /** Set the id of the book. */
    setId(id) {
        this.id = id;
        
        return this;
    }

    /** Set the title of the book. */
    setTitle(title) {
        this.title = title;
        
        return this;
    }

    /** Set the subtitle of the book. */
    setSubtitle(subtitle) {
        this.subtitle = subtitle;
        
        return this;
    }

    /** Set the publication date of the book. */
    setPublicationDate(publicationDate) {
        this.publicationDate = publicationDate;
        
        return this;
    }

    /** Set the created at date of the book. */
    setCreatedAt(createdAt) {
        this.createdAt = createdAt;
        
        return this;
    }

    /** Set the updated at date of the book. */
    setUpdatedAt(updatedAt) {
        this.updatedAt = updatedAt;
        
        return this;
    }

    /** Load a book from a database object. */
    load(dbObject) {
        this.setId(dbObject.id);
        this.setTitle(dbObject.title);
        this.setSubtitle(dbObject.subtitle);
        this.setPublicationDate(new Date(dbObject.publication_date));
        this.setCreatedAt(new Date(dbObject.created_at));
        this.setUpdatedAt(new Date(dbObject.updated_at));
        
        return this;
    }

    /** Create the book. */
    async create() {
        if (!this.id) {
            return null;
        } else if (!this.title && !this.subtitle && !this.publicationDate && !this.createdAt && !this.updatedAt) {
            this.load(await new BookController().byId(this.id));
        }

        return new Book(this.id, this.title, this.publicationDate, this.createdAt, this.updatedAt, this.subtitle);
    }
}

module.exports = { BookFactory, Book };