"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path = require("path");
const osenv_1 = require("osenv");
const util_1 = require("./util");
const validation_1 = require("./validation");
const denodeify = require("denodeify");
const readFile = denodeify(fs.readFile);
const writeFile = denodeify(fs.writeFile);
const storePath = path.join(osenv_1.home(), '.vsce');
function load() {
    return readFile(storePath, 'utf8')
        .catch(err => err.code !== 'ENOENT' ? Promise.reject(err) : Promise.resolve('{}'))
        .then(rawStore => {
        try {
            return Promise.resolve(JSON.parse(rawStore));
        }
        catch (e) {
            return Promise.reject(`Error parsing store: ${storePath}`);
        }
    })
        .then(store => {
        store.publishers = store.publishers || [];
        return Promise.resolve(store);
    });
}
function save(store) {
    return writeFile(storePath, JSON.stringify(store))
        .then(() => store);
}
function addPublisherToStore(store, publisher) {
    store.publishers = [...store.publishers.filter(p => p.name !== publisher.name), publisher];
    return save(store).then(() => publisher);
}
function removePublisherFromStore(store, publisherName) {
    store.publishers = store.publishers.filter(p => p.name !== publisherName);
    return save(store);
}
function requestPAT(store, publisherName) {
    return __awaiter(this, void 0, void 0, function* () {
        const pat = yield util_1.read(`Personal Access Token for publisher '${publisherName}':`, { silent: true, replace: '*' });
        // If the caller of the `getRoleAssignments` API has any of the roles
        // (Creator, Owner, Contributor, Reader) on the publisher, we get a 200,
        // otherwise we get a 403.
        const api = yield util_1.getSecurityRolesAPI(pat);
        yield api.getRoleAssignments('gallery.publisher', publisherName);
        return yield addPublisherToStore(store, { name: publisherName, pat });
    });
}
function getPublisher(publisherName) {
    validation_1.validatePublisher(publisherName);
    return load().then(store => {
        const publisher = store.publishers.filter(p => p.name === publisherName)[0];
        return publisher ? Promise.resolve(publisher) : requestPAT(store, publisherName);
    });
}
exports.getPublisher = getPublisher;
function loginPublisher(publisherName) {
    validation_1.validatePublisher(publisherName);
    return load()
        .then(store => {
        const publisher = store.publishers.filter(p => p.name === publisherName)[0];
        if (publisher) {
            console.log(`Publisher '${publisherName}' is already known`);
            return util_1.read('Do you want to overwrite its PAT? [y/N] ')
                .then(answer => /^y$/i.test(answer) ? store : Promise.reject('Aborted'));
        }
        return Promise.resolve(store);
    })
        .then(store => requestPAT(store, publisherName));
}
exports.loginPublisher = loginPublisher;
function logoutPublisher(publisherName) {
    validation_1.validatePublisher(publisherName);
    return load().then(store => {
        const publisher = store.publishers.filter(p => p.name === publisherName)[0];
        if (!publisher) {
            return Promise.reject(`Unknown publisher '${publisherName}'`);
        }
        return removePublisherFromStore(store, publisherName);
    });
}
exports.logoutPublisher = logoutPublisher;
function createPublisher(publisherName) {
    validation_1.validatePublisher(publisherName);
    return util_1.read(`Publisher human-friendly name: `, { default: publisherName }).then(displayName => {
        return util_1.read(`E-mail: `).then(email => {
            return util_1.read(`Personal Access Token:`, { silent: true, replace: '*' })
                .then((pat) => __awaiter(this, void 0, void 0, function* () {
                const api = yield util_1.getGalleryAPI(pat);
                const raw = {
                    publisherName,
                    displayName,
                    extensions: [],
                    flags: null,
                    lastUpdated: null,
                    longDescription: '',
                    publisherId: null,
                    shortDescription: '',
                    emailAddress: [email]
                };
                yield api.createPublisher(raw);
                return { name: publisherName, pat };
            }))
                .then(publisher => load().then(store => addPublisherToStore(store, publisher)));
        });
    })
        .then(() => util_1.log.done(`Created publisher '${publisherName}'.`));
}
exports.createPublisher = createPublisher;
function deletePublisher(publisherName) {
    return getPublisher(publisherName).then(({ pat }) => {
        return util_1.read(`This will FOREVER delete '${publisherName}'! Are you sure? [y/N] `)
            .then(answer => /^y$/i.test(answer) ? null : Promise.reject('Aborted'))
            .then(() => util_1.getGalleryAPI(pat))
            .then(api => api.deletePublisher(publisherName))
            .then(() => load().then(store => removePublisherFromStore(store, publisherName)))
            .then(() => util_1.log.done(`Deleted publisher '${publisherName}'.`));
    });
}
exports.deletePublisher = deletePublisher;
function listPublishers() {
    return load()
        .then(store => store.publishers)
        .then(publishers => publishers.forEach(p => console.log(p.name)));
}
exports.listPublishers = listPublishers;
