"use strict";
/*
* Each class should work like this....
*
* Take 'source' as an example
*
* 1. class called 'Source' - this is the CORE class. It will have functionality that should USE the data and provide info
*   - REQUIRED to be creatable on the frontend easily too - nothing fancy in constructors or for setup
* 2. class called 'SavedSource' - this is the class that will be derived from Source, and has the ability to save data
*   - should NEVER EVER be used on the frontend, only on the backend
*   - Any sources sent back/forth will be as a Source, not SavedSource
*   - needs to have a constructor that can take a Source and create a SavedSource from it, or the same params as Source
*   - include a 'save' method that will save the data to the database in the class itself
*   - static load and loadMany functions as well - make all functionality derived from here
*
* */
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Source = void 0;
const fs_extra_1 = __importDefault(require("fs-extra"));
const crypto_1 = __importDefault(require("crypto"));
class Source {
    get ready() {
        if (this._hashFinished == null)
            return new Promise((resolve) => {
                resolve(false);
            });
        else
            return this._hashFinished;
    }
    constructor(params = null, avoidHash = false) {
        this.tags = [];
        this._hashFinished = null;
        // if no params, just return empty. Used as template for Object.assign to take over
        if (!params)
            return;
        this.name = params.name;
        this.desc = params.desc;
        this.tags = params.tags ? params.tags : [];
        this.modList = params.modList;
        if (params.blueprint && params.saveGamePath)
            throw new Error('Cannot have both blueprint and savegame path specified in creating a Source');
        if (params.blueprint) {
            this.variant = 'blueprint';
            this.text = params.blueprint.replaceAll('\n', '');
        }
        else if (params.saveGamePath) {
            this.variant = 'savegame';
            this.text = params.saveGamePath;
        }
        else
            throw new Error('Must have either blueprint or savegame path specified in creating a Source');
        if (!avoidHash)
            this._hashFinished = this.updateHash();
    }
    updateHash() {
        return __awaiter(this, void 0, void 0, function* () {
            if (this.text) {
                if (this.variant == 'blueprint') {
                    this.id = crypto_1.default.createHash('sha256').update(this.text).digest('hex');
                    return true;
                }
                else if (this.variant == 'savegame') {
                    // DO I NEED TO HASH SAVEGAME?
                    // IF USER UPLOADS A NEW SAVE, CAN RENAME IT EASILY, THEN USE NEW NAME. CAN JUST HASH SAVEGAME PATH!
                    // will change this if it becomes an issue
                    let buffer = yield fs_extra_1.default.readFile(this.text);
                    this.id = crypto_1.default.createHash('sha256').update(buffer).digest('hex');
                    return true;
                }
                else {
                    throw new Error('Invalid variant for Source');
                }
            }
            else {
                // need to return false here - we are likely on the web!!
                return false;
            }
        });
    }
    addTag(tag) {
        if (!this.tags.includes(tag)) {
            this.tags.push(tag);
        }
    }
    removeTag(tag) {
        if (this.tags.includes(tag)) {
            this.tags.splice(this.tags.indexOf(tag), 1);
        }
    }
}
exports.Source = Source;
//# sourceMappingURL=Source.js.map