<?php

/**
 * 
 * This file is dynamically generated by the WordpressEnqueueChunksPlugin for Webpack.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
 * OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 */

namespace WordpressEnqueueChunksPlugin;

class AssetRegistrationException extends \Exception {};

/**
 * Get a user-defined config setting
 *
 * @param string $key
 * @return mixed
 */
function get($key)
{
    static $config = null;
    if (defined('WPECP_TEST') && WPECP_TEST) {
        return WPECP_TEST_CONFIG[$key];
    }
    if (is_null($config)) {
        $config = json_decode('{"assetsDir":"build","context":"plugin","delimiter":"-","namespace":"cfw","phpScriptDir":"sources/php","manifest":{"chunks":{"cfw-grid":{"file":"css/cfw-grid.css","hash":"ea430b9ce6b4fb581d41a84d0634e308"},"selectwoo-styles":{"file":"css/selectwoo-styles.css","hash":"82fb246cea22eb9311e9774f1f8c46b1"},"selectwoo":{"file":"js/selectwoo-fc86d5cca4a11fc62363.js","hash":"95087c4b021ea781b25862b5d5e641b7"},"slick":{"file":"js/slick-7b818dc4a1705718ef35.js","hash":"fb602538de11326b9be487592c4d9f20"},"default-checkout-order-pay-thank-you-admin-plugins-side-cart":{"file":"js/default-checkout-order-pay-thank-you-admin-plugins-side-cart-59234eecdd8c1560c2ae.js","hash":"f25596a7ad0f0f71eadd11ba38d1ab74"},"default-checkout-order-pay-thank-you":{"file":"js/default-checkout-order-pay-thank-you-e6a3d294bed585b313bf.js","hash":"17e6c828aa73a0a408117bb03307d917"},"default-checkout-order-pay":{"file":"js/default-checkout-order-pay-7c2d873e1953684f44e0.js","hash":"cc307ca8582f8d98539a0d56e1d2de84"},"default-checkout-side-cart":{"file":"js/default-checkout-side-cart-3dde3ea593e160d51aac.js","hash":"81c19f733f55c7bc2a863d7ef3423590"},"checkout-styles":{"file":"css/checkout-styles.css","hash":"9f031c34bb14deb4b0960101eb389961"},"checkout":{"file":"js/checkout-b4cf8bdcb5dbeec7f0f5.js","hash":"120b4ed26bc00b20290f3366f267cf61"},"order-pay-styles":{"file":"css/order-pay-styles.css","hash":"cffc7479f34fe1cce0d43fc80fa8888f"},"order-pay":{"file":"js/order-pay-77536968d9d2cd15fa35.js","hash":"a6ff319c17ae0dcd0952fa4dc0e9a55d"},"thank-you-styles":{"file":"css/thank-you-styles.css","hash":"cd2ce656a8a761959f6fe71a5402364e"},"thank-you":{"file":"js/thank-you-f62901a3d63705cef133.js","hash":"3b7a7acfaaef2000b08e8450430a0049"},"admin-mce":{"file":"js/mce.js","hash":"9f03e96fc23f4adcf779157cf3e563f2"},"admin-styles":{"file":"css/admin-styles.css","hash":"9052349ec144534d2eafba9fd2212bd1"},"admin":{"file":"js/admin-cf04a1d7bda780e46457.js","hash":"45cd9e05d36e794a6135e39d9cfb5309"},"admin-acr-reports":{"file":"js/admin-acr-reports-37c326f267c3900522fb.js","hash":"0d0b5a4d9a3ca0c0da4f63d911f4b8e7"},"admin-settings":{"file":"js/admin-settings-8cee8377c4253cf959ec.js","hash":"0ad804e7246963446a8de27e0abe6bf0"},"admin-plugins-styles":{"file":"css/admin-plugins-styles.css","hash":"18fc11161f2a6258a6bdceef9739944c"},"admin-plugins":{"file":"js/admin-plugins-66db2933421d636bf9c6.js","hash":"833b7febeaeaabc680bc0d91fffe04b1"},"side-cart-styles":{"file":"css/side-cart-styles.css","hash":"4295264204e3d17aabac6d567a528580"},"side-cart":{"file":"js/side-cart-5ac79c713ff81588f4a6.js","hash":"db143df49997341ed40944b6666d038a"},"utils-script":{"file":"js/utils.js","hash":"841a10aa2b6b4e0262c8bd5257043aa4"}},"entries":{"cfw-grid":{"deps":[]},"selectwoo":{"deps":["selectwoo-styles"]},"slick":{"deps":[]},"checkout":{"deps":["default-checkout-order-pay-thank-you-admin-plugins-side-cart","default-checkout-order-pay-thank-you","default-checkout-order-pay","default-checkout-side-cart","checkout-styles"]},"order-pay":{"deps":["default-checkout-order-pay-thank-you-admin-plugins-side-cart","default-checkout-order-pay-thank-you","default-checkout-order-pay","order-pay-styles"]},"thank-you":{"deps":["default-checkout-order-pay-thank-you-admin-plugins-side-cart","default-checkout-order-pay-thank-you","thank-you-styles"]},"admin-mce":{"deps":[]},"admin":{"deps":["admin-styles"]},"admin-acr-reports":{"deps":[]},"admin-settings":{"deps":[]},"admin-plugins":{"deps":["default-checkout-order-pay-thank-you-admin-plugins-side-cart","admin-plugins-styles"]},"side-cart":{"deps":["default-checkout-order-pay-thank-you-admin-plugins-side-cart","default-checkout-side-cart","side-cart-styles"]},"utils-script":{"deps":[]}}},"prefix":"cfw-"}', true);
    }
    return isset($config[$key]) ? $config[$key] : null;
}

/**
 * Get an array of chunks and chunk meta from an array of script names
 * 
 * @param array $assets
 * @param array $manifest
 * @return array
 */
function getChunks(array $assets, array $manifest)
{
    if (empty($assets)) {
        return $manifest['chunks'];
    }
    $deps = array_reduce($assets, function($acc, $asset) use($manifest) {
        if (isset($manifest['entries'][$asset])) {
            return array_merge($acc, $manifest['entries'][$asset]['deps']);
        }
        return $acc;
    }, []);
    $keys = array_flip(array_unique(array_merge($assets, $deps)));
    return array_intersect_key($manifest['chunks'], $keys);
}

/**
 * Builds a script handle
 * 
 * @param string $asset
 * @return string
 */
function makeHandle($asset)
{
    $namespace = get('namespace');
    $delimiter = get('delimiter');
    return "{$namespace}{$delimiter}{$asset}";
}

/**
 * Check if a script has already been registered
 * 
 * @param string $asset
 * @return boolean
 */
function isRegistered($asset)
{
    return wp_script_is(makeHandle($asset), 'registered');
}

/**
 * Get the full url to an asset
 * 
 * @param string $file
 * @param string $context
 * @return string
 */
function getAssetUrl($file, $context)
{
    $dir = trailingslashit(get('assetsDir'));
    if ($context === 'plugin') {
        return plugins_url($dir . $file);
    }
    return get_theme_file_uri($dir . $file);
}

/**
 * Maps an asset's dependencies by handle
 * 
 * @param string $asset
 * @return array
 */
function mapDependencies($asset)
{
    $manifest = get('manifest');
    if (isset($manifest['entries'][$asset])) {
        $deps = $manifest['entries'][$asset]['deps'];
        return array_map(__NAMESPACE__ . '\\makeHandle', $deps);
    }
    return [];
}

/**
 * Generates arguments to be passed to wp_register_script
 * 
 * @param string $asset
 * @param array $data
 * @return array
 */
function makeScriptArgs($asset, array $data)
{
    $handle = makeHandle($asset);
    $src = getAssetUrl($data['file'], get('context'));
    $deps = mapDependencies($asset);
    $version = $data['hash'];
    $inFooter = true; // @TODO: expose this to the user
    return compact('handle', 'src', 'deps', 'version', 'inFooter');
}

/**
 * Register an asset
 * 
 * @param string $asset
 * @param array $args
 * @return boolean
 */
function register($asset, array $args)
{
    if (isRegistered($asset)) {
        return true;
    }
    $filtered = apply_filters("wpecp/register/$asset", $args);
    $success = call_user_func_array('wp_register_script', $filtered);
    if (!$success) {
        throw new AssetRegistrationException("Unable to register asset $asset!");
    }
    return true;
}

/**
 * Registers all or just some of the assets in a manifest
 * 
 * @param array $scripts
 * @return void
 */
function registerScripts(array $scripts = [])
{
    $manifest = get('manifest');
    foreach (getChunks($scripts, $manifest) as $chunk => $data) {
        if (isRegistered($chunk)) {
            continue;
        }
        $args = makeScriptArgs($chunk, $data);
        register($chunk, $args);
    }
}
