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 __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
import { SkillWalletIDBadgeGenerator } from 'sw-web-shared';
import axios from 'axios';
import { SkillWalletAbi } from '@skill-wallet/sw-abi-types';
import dateFormat from 'dateformat';
import { setLoadingMessage, startLoading } from '../../store/sw-ui-reducer';
import { ipfsCIDToHttpUrl, storeMetadata } from '../textile/textile.hub';
import { Web3ContractProvider } from './web3.provider';
import { env } from './env';
import communityAbi from './community-abi.json';
import { ErrorTypes } from '../../types/error-types';
export var getSkillWalletAddress = function () { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2 /*return*/, axios.get("".concat(env.SKILL_WALLET_API, "/skillwallet/config")).then(function (response) { return response.data.skillWalletAddress; })];
    });
}); };
export var getPAKeyByCommunity = function (community) { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2 /*return*/, axios.get("".concat(env.SKILL_WALLET_API, "/community/").concat(community, "/key")).then(function (response) { return response.data; })];
    });
}); };
export var getActivationNonce = function (tokenId) { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2 /*return*/, axios
                .post("".concat(env.SKILL_WALLET_API, "/skillwallet/").concat(tokenId, "/nonces?action=0"))
                .then(function (response) { return response.data.nonce; })
                .catch(function (e) {
                throw new Error(ErrorTypes.CouldNotGetActivationNonce);
            })];
    });
}); };
export var getTokenId = function () { return __awaiter(void 0, void 0, void 0, function () {
    var skillWalletAddress, contract, selectedAddress;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0:
                console.log('fetching address');
                return [4 /*yield*/, getSkillWalletAddress()];
            case 1:
                skillWalletAddress = _a.sent();
                return [4 /*yield*/, Web3ContractProvider(skillWalletAddress, SkillWalletAbi)];
            case 2:
                contract = _a.sent();
                if (window.ethereum.selectedAddress) {
                    selectedAddress = window.ethereum.selectedAddress;
                    console.log('fetching token');
                    return [2 /*return*/, contract.getSkillWalletIdByOwner(selectedAddress)];
                }
                throw Error('Unable to retrieve selected address');
        }
    });
}); };
export var isQrCodeActive = function (tokenId) { return __awaiter(void 0, void 0, void 0, function () {
    var skillwalletAddress, contract, status_1, error_1;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0:
                _a.trys.push([0, 4, , 5]);
                return [4 /*yield*/, getSkillWalletAddress()];
            case 1:
                skillwalletAddress = _a.sent();
                return [4 /*yield*/, Web3ContractProvider(skillwalletAddress, SkillWalletAbi)];
            case 2:
                contract = _a.sent();
                return [4 /*yield*/, contract.isSkillWalletActivated(tokenId)];
            case 3:
                status_1 = _a.sent();
                console.log('Polling qr!', status_1);
                return [2 /*return*/, status_1];
            case 4:
                error_1 = _a.sent();
                console.log(error_1);
                console.log('QR Code verification failed!');
                return [2 /*return*/, false];
            case 5: return [2 /*return*/];
        }
    });
}); };
export var isCoreTeamMember = function (communityAddress, user) { return __awaiter(void 0, void 0, void 0, function () {
    var contract, result;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, Web3ContractProvider(communityAddress, communityAbi)];
            case 1:
                contract = _a.sent();
                return [4 /*yield*/, contract.isCoreTeamMember(user)];
            case 2:
                result = _a.sent();
                return [2 /*return*/, result];
        }
    });
}); };
export var getCommunity = function (partnerKey) { return __awaiter(void 0, void 0, void 0, function () {
    return __generator(this, function (_a) {
        return [2 /*return*/, axios.get("".concat(env.SKILL_WALLET_API, "/community/key/").concat(partnerKey)).then(function (response) { return response.data; })];
    });
}); };
export var joinCommunity = function (communityAddress, username, imageUrl, role, level, dispatch) { return __awaiter(void 0, void 0, void 0, function () {
    var contract, timeStamp, config, toFile, file, metadataJson, url, createTx, communityTransactionResult, events, memberJoinedEvent;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0:
                console.log('trying to join community', communityAddress);
                dispatch(setLoadingMessage('Preparing to join community.'));
                return [4 /*yield*/, Web3ContractProvider(communityAddress, communityAbi)];
            case 1:
                contract = _a.sent();
                timeStamp = dateFormat(new Date(), 'HH:MM:ss | dd/mm/yyyy');
                config = {
                    avatar: ipfsCIDToHttpUrl(imageUrl, false),
                    tokenId: '2',
                    title: username,
                    timestamp: "#".concat(1, " | ").concat(timeStamp),
                };
                return [4 /*yield*/, SkillWalletIDBadgeGenerator(config)];
            case 2:
                toFile = (_a.sent()).toFile;
                return [4 /*yield*/, toFile()];
            case 3:
                file = _a.sent();
                metadataJson = {
                    name: "".concat(username),
                    description: "This is ".concat(username, "'s SkillWallet.      \n      SkillWallets are a new standard for self-sovereign Identities that do not depend from the provider, therefore, they are universal.       \n      They are individual NFT IDs. This one is ").concat(username, "'s.      \n      A SkillWallet cannot be bought - it can only be acquired by joining a decentralized, permissionless Community that lives on the Blockchain.       \n      Each SkillWallet is unique, and based on someone's Skills, rather than exploiting their personal data.      \n      Also, it's non-transferable, so everyone's experience and skills are truly theirs - and keeps track of each contribution they make in the communities they're part of, rewarding them for their participation.\n      SkillWallet is the first Identity you can truly own.      \n      This is  ").concat(username, "'s, and there are no others like this."),
                    image: file,
                    properties: {
                        timestamp: timeStamp,
                        avatar: imageUrl,
                        username: username,
                        roles: [
                            {
                                // eslint-disable-next-line dot-notation
                                name: role.roleName,
                                value: level,
                            },
                        ],
                    },
                };
                dispatch(setLoadingMessage('Uploading metadata.'));
                return [4 /*yield*/, storeMetadata(metadataJson)];
            case 4:
                url = _a.sent();
                dispatch(setLoadingMessage('Awaiting transaction confirmation.'));
                return [4 /*yield*/, contract.joinNewMember(url, role['roleId']).catch(function (e) {
                        if (e.message.includes('No free spots left')) {
                            throw new Error(ErrorTypes.CommunitySlotsFull);
                        }
                        else if (e.message.includes('Already a member')) {
                            throw new Error(ErrorTypes.AlreadyAMember);
                        }
                        else if (e.message.includes('SkillWallet already registered')) {
                            throw new Error(ErrorTypes.SkillWalletWithThisAddressAlreadyRegistered);
                        }
                        else {
                            throw new Error(e.message);
                        }
                    })];
            case 5:
                createTx = _a.sent();
                dispatch(setLoadingMessage('Confirming transaction.'));
                return [4 /*yield*/, createTx.wait()];
            case 6:
                communityTransactionResult = _a.sent();
                console.log(communityTransactionResult);
                events = communityTransactionResult.events;
                memberJoinedEvent = events.find(function (e) { return e.event === 'MemberAdded'; });
                if (memberJoinedEvent) {
                    // return tokenID.
                    return [2 /*return*/, memberJoinedEvent.args[1].toString()];
                }
                throw new Error('Something went wrong');
        }
    });
}); };
export var fetchSkillWallet = function (dispatch, checkIfExists) { return __awaiter(void 0, void 0, void 0, function () {
    var skillWalletAddress, contract, selectedAddress, tokenId, isActive, uriCid, jsonUri, community, partnersAgreementKey, res, jsonMetadata, isCoreTeam, skillWallet;
    return __generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, getSkillWalletAddress()];
            case 1:
                skillWalletAddress = _a.sent();
                if (!window.ethereum.selectedAddress && dispatch) {
                    dispatch(startLoading('Getting MetaMask info. Make sure you are logged into your account.'));
                }
                return [4 /*yield*/, Web3ContractProvider(skillWalletAddress, SkillWalletAbi)];
            case 2:
                contract = _a.sent();
                if (dispatch) {
                    if (checkIfExists) {
                        dispatch(setLoadingMessage('Checking for an existing SkillWallet.'));
                    }
                    else {
                        dispatch(setLoadingMessage('Retrieving SkillWallet.'));
                    }
                }
                if (!window.ethereum.selectedAddress) return [3 /*break*/, 13];
                selectedAddress = window.ethereum.selectedAddress;
                console.log(selectedAddress);
                return [4 /*yield*/, contract.getSkillWalletIdByOwner(selectedAddress).catch(function (e) {
                        if (e.data && e.data.message.includes('invalid')) {
                            throw new Error(ErrorTypes.SkillWalletNotFound);
                        }
                        else {
                            throw e;
                        }
                    })];
            case 3:
                tokenId = _a.sent();
                console.log(tokenId);
                return [4 /*yield*/, contract.isSkillWalletActivated(tokenId)];
            case 4:
                isActive = _a.sent();
                if (!isActive) return [3 /*break*/, 11];
                console.log(isActive);
                return [4 /*yield*/, contract.tokenURI(tokenId)];
            case 5:
                uriCid = _a.sent();
                jsonUri = ipfsCIDToHttpUrl(uriCid, true);
                return [4 /*yield*/, contract.getActiveCommunity(tokenId)];
            case 6:
                community = _a.sent();
                console.log(community);
                return [4 /*yield*/, getPAKeyByCommunity(community)];
            case 7:
                partnersAgreementKey = _a.sent();
                console.log(partnersAgreementKey);
                return [4 /*yield*/, fetch(jsonUri)];
            case 8:
                res = _a.sent();
                return [4 /*yield*/, res.json()];
            case 9:
                jsonMetadata = _a.sent();
                return [4 /*yield*/, isCoreTeamMember(partnersAgreementKey.communityAddress, selectedAddress)];
            case 10:
                isCoreTeam = _a.sent();
                skillWallet = {
                    imageUrl: ipfsCIDToHttpUrl(jsonMetadata.properties.avatar, false),
                    nickname: jsonMetadata.properties.username,
                    skills: jsonMetadata.properties.skills,
                    community: community,
                    partnersAgreementKey: partnersAgreementKey,
                    diToCredits: 0,
                    tokenId: tokenId.toString(),
                    isCoreTeamMember: isCoreTeam,
                    timestamp: new Date().getTime(),
                };
                if (skillWallet && skillWallet.nickname) {
                    return [2 /*return*/, skillWallet];
                }
                if (!skillWallet) {
                    throw new Error(ErrorTypes.SkillWalletNotFound);
                }
                return [3 /*break*/, 12];
            case 11: throw new Error(ErrorTypes.SkillWalletExistsButInactive);
            case 12: return [3 /*break*/, 14];
            case 13: throw new Error('No selected wallet address.');
            case 14: return [2 /*return*/];
        }
    });
}); };
