"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CertificationRequest = exports.MAX_ENERGY_PER_CERTIFICATE = void 0;
const ethers_1 = require("ethers");
const events_1 = require("../utils/events");
const CertificateUtils_1 = require("./CertificateUtils");
// Maximum number Solidity can handle is (2^256)-1
exports.MAX_ENERGY_PER_CERTIFICATE = ethers_1.BigNumber.from(2).pow(256).sub(1);
class CertificationRequest {
    constructor(id, blockchainProperties) {
        this.id = id;
        this.blockchainProperties = blockchainProperties;
        this.initialized = false;
    }
    /**
     *
     *
     * @description Uses Issuer contract to create Certificate request
     *
     */
    static create(generationStartTime, generationEndTime, deviceId, blockchainProperties, forAddress) {
        return __awaiter(this, void 0, void 0, function* () {
            const newCertificationRequest = new CertificationRequest(null, blockchainProperties);
            const { issuer, activeUser } = blockchainProperties;
            const issuerWithSigner = issuer.connect(activeUser);
            const data = (0, CertificateUtils_1.encodeData)({ generationStartTime, generationEndTime, deviceId, metadata: '' });
            const tx = yield (forAddress
                ? issuerWithSigner.requestCertificationFor(data, forAddress)
                : issuerWithSigner.requestCertification(data));
            const { events: [certificationRequested] } = yield tx.wait();
            const log = issuer.interface.decodeEventLog(certificationRequested.event, certificationRequested.data, certificationRequested.topics);
            newCertificationRequest.id = log._id.toNumber();
            return newCertificationRequest.sync();
        });
    }
    /**
    *
    *
    * @description Returns all Certification Requests for an Issuer
    *
    */
    static getAll(blockchainProperties) {
        return __awaiter(this, void 0, void 0, function* () {
            const { issuer } = blockchainProperties;
            const certificationRequestedEvents = yield (0, events_1.getEventsFromContract)(issuer, issuer.filters.CertificationRequested(null, null));
            return certificationRequestedEvents.map((event) => new CertificationRequest(event._id, blockchainProperties));
        });
    }
    /**
   *
   *
   * @description Retrieves Certificate data
   *
   */
    sync() {
        var _a, _b;
        return __awaiter(this, void 0, void 0, function* () {
            if (this.id === null) {
                return this;
            }
            const { issuer } = this.blockchainProperties;
            const issueRequest = yield issuer.getCertificationRequest(this.id);
            const decodedData = (0, CertificateUtils_1.decodeData)(issueRequest.data);
            this.owner = issueRequest.owner;
            this.fromTime = decodedData.generationStartTime;
            this.toTime = decodedData.generationEndTime;
            this.deviceId = decodedData.deviceId;
            this.approved = issueRequest.approved;
            this.revoked = issueRequest.revoked;
            const certificationRequestedLogs = yield (0, events_1.getEventsFromContract)(issuer, issuer.filters.CertificationRequested(null, this.id));
            const certificationApprovedLogs = yield (0, events_1.getEventsFromContract)(issuer, issuer.filters.CertificationRequestApproved(null, this.id, null));
            this.issuedCertificateTokenId =
                (_b = (_a = certificationApprovedLogs[0]) === null || _a === void 0 ? void 0 : _a._certificateId.toNumber()) !== null && _b !== void 0 ? _b : null;
            const creationBlock = yield issuer.provider.getBlock(certificationRequestedLogs[0].blockNumber);
            this.created = Number(creationBlock.timestamp);
            this.initialized = true;
            return this;
        });
    }
    /**
   *
   *
   * @description Uses Issuer contract to approve a Certificate request
   *
   */
    approve(energy) {
        return __awaiter(this, void 0, void 0, function* () {
            const { issuer, activeUser } = this.blockchainProperties;
            const issuerWithSigner = issuer.connect(activeUser);
            const approveTx = yield issuerWithSigner.approveCertificationRequest(this.id, energy);
            const { events } = yield approveTx.wait();
            const certificateId = Number(events.find((log) => log.event === 'CertificationRequestApproved')
                .topics[3]);
            this.issuedCertificateTokenId = certificateId;
            return certificateId;
        });
    }
    /**
   *
   *
   * @description Uses Issuer contract to revoke a Certificate request
   *
   */
    revoke() {
        return __awaiter(this, void 0, void 0, function* () {
            const { issuer, activeUser } = this.blockchainProperties;
            const issuerWithSigner = issuer.connect(activeUser);
            const revokeTx = yield issuerWithSigner.revokeRequest(this.id);
            yield revokeTx.wait();
            return revokeTx;
        });
    }
}
exports.CertificationRequest = CertificationRequest;
//# sourceMappingURL=CertificationRequest.js.map