import BaseFile from "../base/file.js";
import PrivateHistory from "./PrivateHistory.js";
import { hasProp, isObject } from "../../common/type-checks.js";
import { decodeCID } from "../../common/index.js";
import * as crypto from "../../crypto/index.js";
import * as check from "../protocol/private/types/check.js";
import * as metadata from "../metadata.js";
import * as protocol from "../protocol/index.js";
import * as namefilter from "../protocol/private/namefilter.js";
import * as versions from "../versions.js";
export class PrivateFile extends BaseFile {
    constructor({ content, mmpt, key, header }) {
        super(content);
        this.header = header;
        this.history = new PrivateHistory(this);
        this.key = key;
        this.mmpt = mmpt;
    }
    static instanceOf(obj) {
        return isObject(obj)
            && hasProp(obj, "content")
            && hasProp(obj, "mmpt")
            && hasProp(obj, "header")
            && check.isPrivateFileInfo(obj.header);
    }
    static async create(mmpt, content, parentNameFilter, key) {
        const bareNameFilter = await namefilter.addToBare(parentNameFilter, key);
        const contentKey = await crypto.aes.genKeyStr();
        const contentInfo = await protocol.basic.putEncryptedFile(content, contentKey);
        return new PrivateFile({
            content,
            mmpt,
            key,
            header: {
                bareNameFilter,
                key: contentKey,
                revision: 1,
                metadata: metadata.empty(true, versions.latest),
                content: contentInfo.cid
            }
        });
    }
    static async fromBareNameFilter(mmpt, bareNameFilter, key) {
        const info = await protocol.priv.getLatestByBareNameFilter(mmpt, bareNameFilter, key);
        return this.fromInfo(mmpt, key, info);
    }
    static async fromLatestName(mmpt, name, key) {
        const info = await protocol.priv.getLatestByName(mmpt, name, key);
        return PrivateFile.fromInfo(mmpt, key, info);
    }
    static async fromName(mmpt, name, key) {
        const info = await protocol.priv.getByName(mmpt, name, key);
        return PrivateFile.fromInfo(mmpt, key, info);
    }
    static async fromInfo(mmpt, key, info) {
        if (!check.isPrivateFileInfo(info)) {
            throw new Error(`Could not parse a valid private file using the given key`);
        }
        const content = await protocol.basic.getEncryptedFile(decodeCID(info.content), info.key);
        return new PrivateFile({
            content,
            key,
            mmpt,
            header: info
        });
    }
    async getName() {
        const { bareNameFilter, revision } = this.header;
        const revisionFilter = await namefilter.addRevision(bareNameFilter, this.key, revision);
        return namefilter.toPrivateName(revisionFilter);
    }
    async updateParentNameFilter(parentNameFilter) {
        this.header.bareNameFilter = await namefilter.addToBare(parentNameFilter, this.header.key);
        return this;
    }
    async updateContent(content) {
        const contentInfo = await protocol.basic.putEncryptedFile(content, this.header.key);
        this.content = content;
        this.header = {
            ...this.header,
            revision: this.header.revision + 1,
            content: contentInfo.cid
        };
        return this;
    }
    async putDetailed() {
        return protocol.priv.addNode(this.mmpt, {
            ...this.header,
            metadata: metadata.updateMtime(this.header.metadata)
        }, this.key);
    }
}
export default PrivateFile;
//# sourceMappingURL=PrivateFile.js.map