Source: controllers/ScanController.js

/** @module controllers */

const BaseDatabaseController = require("./BaseDatabaseController");

/** Class representing a scan controller. */
class ScanController extends BaseDatabaseController {
    /** Create a scan controller. */
    constructor() {
        super();
    }

    /**
     * Get an scan by id.
     * 
     * @param {number} id
     * @returns {Promise<object>}
     */
    async byId(id) {
        const scanResponse = await this._query('SELECT * FROM scans WHERE id = ?', id);
        if (scanResponse.length !== 1) {
            return null;
        }

        return scanResponse[0];
    }

    /**
     * Get scans by user.
     * 
     * @param {number} userId
     * @returns {Promise<object[]>}
     */
    async byUser(userId) {
        const scansResponse = await this._query('SELECT * FROM scans WHERE user_id = ?', userId);

        return scansResponse;
    }

    /**
     * Change the amount of spines segmented by a certain amount.
     * 
     * @param {number} scanId
     * @param {number} amount
     * @returns {Promise<void>}
     */
    async changeSpinesSegmentedBy(scanId, amount) {
        await this._query('UPDATE scans SET amount_of_spines_segmented = amount_of_spines_segmented + ? WHERE id = ?', amount, scanId);
    }

    /**
     * Change the amount of books identified by a certain amount.
     * 
     * @param {number} scanId
     * @param {number} amount
     * @returns {Promise<void>}
     */
    async changeBooksIdentified(scanId, amount) {
        await this._query('UPDATE scans SET amount_of_books_identified = amount_of_books_identified + ? WHERE id = ?', amount, scanId);
    }

    /**
     * Change the image path of a scan.
     * 
     * @param {number} scanId
     * @param {string} imagePath
     * @returns {Promise<void>}
     */
    async changeImagePath(scanId, imagePath) {
        await this._query('UPDATE scans SET image_path = ? WHERE id = ?', imagePath, scanId);
    }

    /**
     * Get the results of a scan including books and authors.
     * 
     * @param {number} scanId
     * @returns {Promise<object[]>}
     */
    async getResultsAndData(scanId) {
        const bookResults = await this._query('SELECT b.*, sr.segment FROM books AS b INNER JOIN scan_results AS sr ON b.id = sr.book_id WHERE sr.scan_id = ?', scanId);
        const authorResults = await this._query('SELECT a.*, ba.books_id FROM authors AS a INNER JOIN books_authors AS ba ON a.id = ba.authors_id INNER JOIN scan_results AS sr ON ba.books_id = sr.book_id WHERE sr.scan_id = ?', scanId);
        const resultsResponse = bookResults.map((book) => {
            const authors = authorResults.filter((author) => author.books_id === book.id);
            return {
                ...book,
                authors,
            };
        });

        return resultsResponse;
    }

    /**
     * Insert scan result.
     * 
     * @param {number} scanId
     * @param {number} bookId
     * @param {object} segmentJson
     * @returns {Promise<void>}
     */
    async insertResult(scanId, bookId, segmentJson) {
        await this._query('INSERT INTO scan_results (scan_id, book_id, segment) VALUES (?, ?, ?)', scanId, bookId, JSON.stringify(segmentJson));
    }

    /**
     * Update the status of a scan.
     * 
     * @param {number} scanId
     * @param {string} status
     * @returns {Promise<void>}
     */
    async updateStatus(scanId, status) {
        await this._query('UPDATE scans SET status = ? WHERE id = ?', status, scanId);
    }

    /**
     * Insert a new scan.
     * 
     * @param {number} userId
     * @returns {Promise<object>}
     */
    async insert(userId) {
        const response = await this._query('INSERT INTO scans (user_id) VALUES (?)', userId);
        return await this.byId(response.insertId);
    }

    /**
     * Insert a new scan with a location.
     * 
     * @param {number} userId
     * @param {number} latitude
     * @param {number} longitude
     * @returns {Promise<void>}
     */
    async insertWithLocation(userId, latitude, longitude) {
        const response = await this._query('INSERT INTO scans (user_id, location) VALUES (?, POINT(?, ?))', userId, latitude, longitude);
        return await this.byId(response.insertId);
    }

    /**
     * Delete a scan.
     * 
     * @param {number} scanId
     * @returns {Promise<void>}
     */
    async delete(scanId) {
        await this._query('DELETE FROM scans WHERE id = ?', scanId);
    }
}

module.exports = ScanController;