const FAKE_SDK = false;

// arkadium unity wrapper state
const arkSt = {
    api: undefined,
    loaded: false,
	logsEnabled: true,
    load(environment) {
        if (!this.loaded && !this.loading) {
            if ('ArkadiumGameSDK' in window) {
                this.loaded = true; // the arena may have loaded the SDK for us
                return Promise.resolve();
            }
            this.loading = this.loadInternal(environment);
            return this.loading;
        } else if (!this.loaded) {
            return this.loading;
        } else {
            return Promise.resolve();
        }
    },
    loadInternal(environment) {
        const gameObjectName = this.gameObjectName
        return new Promise((resolve) => {
            let isDev = environment === 'DEV';

            // check if environment should be fetched from url params
            if(environment === 'URL') {
                const urlParams = new URLSearchParams(window.location.search);
                isDev = urlParams.get('useSDKDevCDN') === 'true';
            }

            log('initializing', [isDev ? 'DEV' : 'PROD', gameObjectName]);
            
            const el = document.createElement('script');
            el.src = `https://developers.arkadium.com/cdn/sdk/${isDev ? 'dev/' : ''}v2/sdk.js`;
            document.head.appendChild(el);
            el.addEventListener('load', () => {
                this.loaded = true;
                resolve();
            });
        });
    }
};
window.arkSt = arkSt;

if (FAKE_SDK) {
    const log = (...args) => {
		console.log('%cFakeSDK', 'color: purple', ...args);
    }

    const api = {
        ads: {
            showInterstitialAd(...args) {
                log('api.ads.showInterstitialAd', args);
                return Promise.resolve();
            },
            showRewardAd(...args) {
                log('api.ads.showRewardAd', ...args);
                return Promise.resolve({ value: 1 });
            },
            showBannerAd(elementId, adSizes) {
                log('api.ads.showBannerAd', [elementId, adSizes]);
                const el = document.getElementById(elementId);
                if (el) {
                    el.style.background = 'red';
                    return Promise.resolve(true);
                }
                return Promise.resolve(false);
            }
        },
        analytics: {
            configureProvider(config) {
                log('api.analytics.configureProvider', [config]);
                return Promise.resolve();
            },
            sendEvent(eventCategory, eventAction, dimensionsObj) {
                log('api.analytics.sendEvent', [eventCategory, eventAction, dimensionsObj]);
                return Promise.resolve();
            },
            sendPageView(pageName, dimensionsObj) {
                log('api.analytics.sendPageView', [pageName, dimensionsObj]);
                return Promise.resolve();
            },
            setDimensions(dimensionsObj) {
                log('api.analytics.setDimensions', [dimensionsObj]);
                return Promise.resolve();
            }
        },
        auth: {
            isUserAuthorized(...args) {
                log('api.auth.isUserAuthorized', args);
                return Promise.resolve(true);
            },
            getUserProfile(...args) {
                log('api.auth.getUserProfile', args);
                return Promise.resolve({ profileParam: 'profileValue' });
            },
            onAuthStatusChange(...args) {
                log('api.auth.onAuthStatusChange', args);
                return Promise.resolve();
            },
            openAuthForm(...args) {
                log('api.auth.openAuthForm', args);
                return Promise.resolve();
            },
        },
        host: {
            openPurchaseForm(...args) {
                log('api.host.openPurchaseForm', args);
                return Promise.resolve();
            },
            getQueryParameter(key) {
                log('api.host.getQueryParameter', [key]);
                return Promise.resolve(`${key}-value`);
            },
            getDetails() {
                log('api.host.getDetails', []);
                return Promise.resolve({
                    GameKey: 'game-key',
                    GameVersion: 'game-version',
                    NestVersion: 'nest-version',
                    SdkVersion: 'sdk-version',
                });
            },
        },
        wallet: (() => {
            const inventory = Object.create(null);
            inventory.mock_item = { sku: 'mock_item', amount: 3 };
            inventory.mock_consumable = { sku: 'mock_consumable', amount: 1 };

            const catalog = Object.create(null);
            catalog.mock_item = { sku: 'mock_item', amount: 0 };
            catalog.mock_consumable = { sku: 'mock_consumable', amount: 0 };
            catalog.mock_bonus = { sku: 'mock_bonus', amount: 0 };

            const bundles = Object.create(null);
            bundles.mock_bundle = {
                sku: 'mock_bundle',
                price: 100,
                salesPrice: 75,
                salesEndDate: '2099-12-31T23:59:59Z',
                isSalesActive: true,
                contents: [
                    { sku: 'mock_item', amount: 2 },
                    { sku: 'mock_bonus', amount: 1 },
                ],
            };

            const clone = value => JSON.parse(JSON.stringify(value));
            const maxItemAmount = 2147483647;
            const hasItem = sku => Object.prototype.hasOwnProperty.call(inventory, sku);
            const getItemAmount = sku => hasItem(sku) ? inventory[sku].amount : 0;
            const canAddItem = (sku, amount) => {
                if (!sku || !Number.isInteger(amount) || amount <= 0 || amount > maxItemAmount) {
                    return false;
                }

                return getItemAmount(sku) + amount <= maxItemAmount;
            };
            const addItem = (sku, amount) => {
                if (!canAddItem(sku, amount)) {
                    return false;
                }

                if (hasItem(sku)) {
                    inventory[sku].amount += amount;
                    return true;
                }

                inventory[sku] = { sku, amount };
                return true;
            };
            const getBundleAdditions = (bundle, amount) => {
                const additions = Object.create(null);

                for (const item of bundle.contents || []) {
                    if (!item ||
                        !item.sku ||
                        !Number.isInteger(item.amount) ||
                        item.amount <= 0) {
                        return null;
                    }

                    const quantity = item.amount * amount;
                    if (!Number.isSafeInteger(quantity) || quantity > maxItemAmount) {
                        return null;
                    }

                    additions[item.sku] = (additions[item.sku] || 0) + quantity;
                    if (!Number.isSafeInteger(additions[item.sku]) ||
                        additions[item.sku] > maxItemAmount) {
                        return null;
                    }
                }

                return additions;
            };

            return {
                isGemsSupported(...args) {
                    log('api.wallet.isGemsSupported', args);
                    return Promise.resolve(true);
                },
                getGems(...args) {
                    log('api.wallet.getGems', args);
                    return Promise.resolve(10000);
                },
                consumeGems(value) {
                    log('api.wallet.consumeGems', [value]);
                    return Promise.resolve(true);
                },
                getInventory() {
                    log('api.wallet.getInventory', []);
                    return Promise.resolve(clone(inventory));
                },
                getInventoryItemAmount(sku) {
                    log('api.wallet.getInventoryItemAmount', [sku]);
                    return Promise.resolve(getItemAmount(sku));
                },
                consumeInventoryItem(sku, amount = 1) {
                    log('api.wallet.consumeInventoryItem', [sku, amount]);
                    if (!Number.isInteger(amount) ||
                        amount <= 0 ||
                        !hasItem(sku) ||
                        getItemAmount(sku) < amount) {
                        return Promise.resolve(false);
                    }

                    inventory[sku].amount -= amount;
                    if (inventory[sku].amount === 0) {
                        delete inventory[sku];
                    }

                    return Promise.resolve(true);
                },
                hasInventoryItem(sku, amount = 1) {
                    log('api.wallet.hasInventoryItem', [sku, amount]);
                    return Promise.resolve(
                        Number.isInteger(amount) &&
                        amount > 0 &&
                        getItemAmount(sku) >= amount
                    );
                },
                getBundles() {
                    log('api.wallet.getBundles', []);
                    return Promise.resolve(clone(bundles));
                },
                purchaseBundle(bundleSku, amount = 1) {
                    log('api.wallet.purchaseBundle', [bundleSku, amount]);
                    const bundle = bundles[bundleSku];
                    if (!Number.isInteger(amount) || amount <= 0 || !bundle) {
                        return Promise.resolve(false);
                    }

                    const additions = getBundleAdditions(bundle, amount);
                    if (!additions ||
                        !Object.entries(additions).every(([sku, quantity]) => canAddItem(sku, quantity))) {
                        return Promise.resolve(false);
                    }

                    Object.entries(additions).forEach(([sku, quantity]) => addItem(sku, quantity));
                    return Promise.resolve(true);
                },
                getCatalog() {
                    log('api.wallet.getCatalog', []);
                    return Promise.resolve(clone(catalog));
                },
                grantCatalogItem(itemSku, amount = 1) {
                    log('api.wallet.grantCatalogItem', [itemSku, amount]);
                    if (!Number.isInteger(amount) ||
                        amount <= 0 ||
                        !Object.prototype.hasOwnProperty.call(catalog, itemSku)) {
                        return Promise.resolve(false);
                    }

                    return Promise.resolve(addItem(itemSku, amount));
                }
            };
        })(),
        lifecycle: {
            onTestReady() {
                log('api.lifecycle.onTestReady', []);
            },
            onInteract() {
                log('api.lifecycle.onInteract', []);
            },
            onGameStart() {
                log('api.lifecycle.onGameStart', []);
            },
            onGameEnd() {
                log('api.lifecycle.onGameEnd', []);
            },
            onGameResume() {
                log('api.lifecycle.onGameResume', []);
            },
            onPauseReady() {
                log('api.lifecycle.onPauseReady', []);
            },
            onGamePause() {
                log('api.lifecycle.onGamePause', []);
            },
            onChangeScore(score) {
                log('api.lifecycle.onChangeScore', [score]);
            },
            onGemsUpdate(score) {
                log('api.lifecycle.onGemsUpdate', []);
            },
            onLevelStart(level) {
                log('api.lifecycle.onLevelStart', [level]);
            },
            onLevelEnd(level) {
                log('api.lifecycle.onLevelEnd', [level]);
            }
        },
        persistence: {
            setLocalStorageItem(...args) {
                log('api.persistence.setLocalStorageItem', args);
                return Promise.resolve();
            },
            getLocalStorageItem(...args) {
                log('api.persistence.getLocalStorageItem', args);
                return Promise.resolve('bogus');
            },
            removeLocalStorageItem(...args) {
                log('api.persistence.removeLocalStorageItem', args);
                return Promise.resolve();
            },
            getCookie(...args) {
                log('api.persistence.getCookie', args);
                return Promise.resolve('bogus');
            }
        },
    }

    arkSt.loadInternal = () => {
        return new Promise((resolve) => {
            log('fake load script');

            setTimeout(() => {
                window.ArkadiumGameSDK = {
                    getInstance(env) {
                        return Promise.resolve(api);
                    }
                }
                this.loaded = true;
                resolve();
                log('fake load done');
            }, 200);
        });
    };
}
