/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import fs from 'fs';
import { ManualPromise } from '@isomorphic/manualPromise';
import { assert } from '@isomorphic/assert';
import { TargetClosedError } from './errors';
import { SdkObject } from './instrumentation';
export class Artifact extends SdkObject {
    _localPath;
    _unaccessibleErrorMessage;
    _cancelCallback;
    _finishedPromise = new ManualPromise();
    _saveCallbacks = [];
    _finished = false;
    _deleted = false;
    _failureErrorValue;
    constructor(parent, localPath, unaccessibleErrorMessage, cancelCallback) {
        super(parent, 'artifact');
        this._localPath = localPath;
        this._unaccessibleErrorMessage = unaccessibleErrorMessage;
        this._cancelCallback = cancelCallback;
    }
    async localPathAfterFinished(progress) {
        return await progress.race(this._localPathAfterFinished());
    }
    async failureError(progress) {
        return await progress.race(this._failureError());
    }
    async cancel(progress) {
        return await progress.race(this._cancel());
    }
    async delete(progress) {
        return await progress.race(this._delete());
    }
    localPath() {
        return this._localPath;
    }
    async _localPathAfterFinished() {
        if (this._unaccessibleErrorMessage)
            throw new Error(this._unaccessibleErrorMessage);
        await this._finishedPromise;
        if (this._failureErrorValue)
            throw this._failureErrorValue;
        return this._localPath;
    }
    saveAs(progress, saveCallback) {
        if (this._unaccessibleErrorMessage)
            throw new Error(this._unaccessibleErrorMessage);
        if (this._deleted)
            throw new Error(`File already deleted. Save before deleting.`);
        if (this._failureErrorValue)
            throw this._failureErrorValue;
        if (this._finished) {
            saveCallback(this._localPath).catch(() => { });
            return;
        }
        this._saveCallbacks.push(saveCallback);
    }
    async _failureError() {
        if (this._unaccessibleErrorMessage)
            return this._unaccessibleErrorMessage;
        await this._finishedPromise;
        return this._failureErrorValue?.message || null;
    }
    async _cancel() {
        assert(this._cancelCallback !== undefined);
        return this._cancelCallback();
    }
    async _delete() {
        if (this._unaccessibleErrorMessage)
            return;
        const fileName = await this._localPathAfterFinished();
        if (this._deleted)
            return;
        this._deleted = true;
        if (fileName)
            await fs.promises.unlink(fileName).catch(e => { });
    }
    async deleteOnContextClose() {
        // Compared to "delete", this method does not wait for the artifact to finish.
        // We use it when closing the context to avoid stalling.
        if (this._deleted)
            return;
        this._deleted = true;
        if (!this._unaccessibleErrorMessage)
            await fs.promises.unlink(this._localPath).catch(e => { });
        await this.reportFinished(new TargetClosedError(this.closeReason()));
    }
    async reportFinished(error) {
        if (this._finished)
            return;
        this._finished = true;
        this._failureErrorValue = error;
        if (error) {
            for (const callback of this._saveCallbacks)
                await callback('', error);
        }
        else {
            for (const callback of this._saveCallbacks)
                await callback(this._localPath);
        }
        this._saveCallbacks = [];
        this._finishedPromise.resolve();
    }
}
//# sourceMappingURL=artifact.js.map