/*
 * Copyright (C) 2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// https://whatwg.github.io/loader/#loader-object
// Module Loader has several hooks that can be customized by the platform.
// For example, the [[Fetch]] hook can be provided by the JavaScriptCore shell
// as fetching the payload from the local file system.
// Currently, there are 4 hooks.
//    1. Loader.resolve
//    2. Loader.fetch
//    3. Loader.translate
//    4. Loader.instantiate

function setStateToMax(entry, newState)
{
    // https://whatwg.github.io/loader/#set-state-to-max

    "use strict";

    if (entry.state < newState)
        entry.state = newState;
}

function newRegistryEntry(key)
{
    // https://whatwg.github.io/loader/#registry
    //
    // Each registry entry becomes one of the 5 states.
    // 1. Fetch
    //     Ready to fetch (or now fetching) the resource of this module.
    //     Typically, we fetch the source code over the network or from the file system.
    //     a. If the status is Fetch and there is no entry.fetch promise, the entry is ready to fetch.
    //     b. If the status is Fetch and there is the entry.fetch promise, the entry is just fetching the resource.
    //
    // 2. Translate
    //     Ready to translate (or now translating) the raw fetched resource to the ECMAScript source code.
    //     We can insert the hook that translates the resources e.g. transpilers.
    //     a. If the status is Translate and there is no entry.translate promise, the entry is ready to translate.
    //     b. If the status is Translate and there is the entry.translate promise, the entry is just translating
    //        the payload to the source code.
    //
    // 3. Instantiate (AnalyzeModule)
    //     Ready to instantiate (or now instantiating) the module record from the fetched (and translated)
    //     source code.
    //     Typically, we parse the module code, extract the dependencies and binding information.
    //     a. If the status is Instantiate and there is no entry.instantiate promise, the entry is ready to instantiate.
    //     b. If the status is Instantiate and there is the entry.translate promise, the entry is just instantiating
    //        the module record.
    //
    // 4. ResolveDependencies (not in the draft) https://github.com/whatwg/loader/issues/68
    //     Ready to request the dependent modules (or now requesting & resolving).
    //     Without this state, the current draft causes infinite recursion when there is circular dependency.
    //     a. If the status is ResolveDependencies and there is no entry.resolveDependencies promise, the entry is ready to resolve the dependencies.
    //     b. If the status is ResolveDependencies and there is the entry.resolveDependencies promise, the entry is just resolving
    //        the dependencies.
    //
    // 5. Link
    //     Ready to link the module with the other modules.
    //     Linking means that the module imports and exports the bindings from/to the other modules.
    //
    // 6. Ready
    //     The module is linked, so the module is ready to be executed.
    //
    // Each registry entry has the 4 promises; "fetch", "translate", "instantiate" and "resolveDependencies".
    // They are assigned when starting the each phase. And they are fulfilled when the each phase is completed.
    //
    // In the current module draft, linking will be performed after the whole modules are instantiated and the dependencies are resolved.
    // And execution is also done after the all modules are linked.
    //
    // TODO: We need to exploit the way to execute the module while fetching non-related modules.
    // One solution; introducing the ready promise chain to execute the modules concurrently while keeping
    // the execution order.

    "use strict";

    return {
        key: key,
        state: this.Fetch,
        metadata: undefined,
        fetch: undefined,
        translate: undefined,
        instantiate: undefined,
        resolveDependencies: undefined,
        dependencies: [], // To keep the module order, we store the module keys in the array.
        dependenciesMap: undefined,
        module: undefined, // JSModuleRecord
        error: undefined,
    };
}

function ensureRegistered(key)
{
    // https://whatwg.github.io/loader/#ensure-registered

    "use strict";

    var entry = this.registry.@get(key);
    if (entry)
        return entry;

    entry = this.newRegistryEntry(key);
    this.registry.@set(key, entry);

    return entry;
}

function forceFulfillPromise(promise, value)
{
    "use strict";

    if (promise.@promiseState === @promisePending)
        @fulfillPromise(promise, value);
}

function fulfillFetch(entry, payload)
{
    // https://whatwg.github.io/loader/#fulfill-fetch

    "use strict";

    if (!entry.fetch)
        entry.fetch = @newPromiseCapability(@InternalPromise).@promise;
    this.forceFulfillPromise(entry.fetch, payload);
    this.setStateToMax(entry, this.Translate);
}

function fulfillTranslate(entry, source)
{
    // https://whatwg.github.io/loader/#fulfill-translate

    "use strict";

    if (!entry.translate)
        entry.translate = @newPromiseCapability(@InternalPromise).@promise;
    this.forceFulfillPromise(entry.translate, source);
    this.setStateToMax(entry, this.Instantiate);
}

function fulfillInstantiate(entry, optionalInstance, source)
{
    // https://whatwg.github.io/loader/#fulfill-instantiate

    "use strict";

    if (!entry.instantiate)
        entry.instantiate = @newPromiseCapability(@InternalPromise).@promise;
    this.commitInstantiated(entry, optionalInstance, source);

    // FIXME: The draft fulfills the promise in the CommitInstantiated operation.
    // But it CommitInstantiated is also used in the requestInstantiate and
    // we should not "force fulfill" there.
    // So we separate "force fulfill" operation from the CommitInstantiated operation.
    // https://github.com/whatwg/loader/pull/67
    this.forceFulfillPromise(entry.instantiate, entry);
}

function commitInstantiated(entry, optionalInstance, source)
{
    // https://whatwg.github.io/loader/#commit-instantiated

    "use strict";

    var moduleRecord = this.instantiation(optionalInstance, source, entry);

    // FIXME: Described in the draft,
    //   4. Fulfill entry.[[Instantiate]] with instance.
    // But, instantiate promise should be fulfilled with the entry.
    // We remove this statement because instantiate promise will be
    // fulfilled without this "force fulfill" operation.
    // https://github.com/whatwg/loader/pull/67

    var dependencies = [];
    var dependenciesMap = moduleRecord.dependenciesMap;
    moduleRecord.registryEntry = entry;
    var requestedModules = this.requestedModules(moduleRecord);
    for (var i = 0, length = requestedModules.length; i < length; ++i) {
        var depKey = requestedModules[i];
        var pair = {
            key: depKey,
            value: undefined
        };
        @putByValDirect(dependencies, i, pair);
        dependenciesMap.@set(depKey, pair);
    }
    entry.dependencies = dependencies;
    entry.dependenciesMap = dependenciesMap;
    entry.module = moduleRecord;
    this.setStateToMax(entry, this.ResolveDependencies);
}

function instantiation(result, source, entry)
{
    // https://whatwg.github.io/loader/#instantiation
    // FIXME: Current implementation does not support optionalInstance.
    // https://bugs.webkit.org/show_bug.cgi?id=148171

    "use strict";

    return this.parseModule(entry.key, source);
}

// Loader.

function requestFetch(key)
{
    // https://whatwg.github.io/loader/#request-fetch

    "use strict";

    var entry = this.ensureRegistered(key);
    if (entry.state > this.Link) {
        var deferred = @newPromiseCapability(@InternalPromise);
        deferred.@reject.@call(undefined, new @TypeError("Requested module is already ready to be executed."));
        return deferred.@promise;
    }

    if (entry.fetch)
        return entry.fetch;

    var loader = this;

    // Hook point.
    // 2. Loader.fetch
    //     https://whatwg.github.io/loader/#browser-fetch
    //     Take the key and fetch the resource actually.
    //     For example, JavaScriptCore shell can provide the hook fetching the resource
    //     from the local file system.
    var fetchPromise = this.fetch(key).then(function (payload) {
        loader.setStateToMax(entry, loader.Translate);
        return payload;
    });
    entry.fetch = fetchPromise;
    return fetchPromise;
}

function requestTranslate(key)
{
    // https://whatwg.github.io/loader/#request-translate

    "use strict";

    var entry = this.ensureRegistered(key);
    if (entry.state > this.Link) {
        var deferred = @newPromiseCapability(@InternalPromise);
        deferred.@reject.@call(undefined, new @TypeError("Requested module is already ready to be executed."));
        return deferred.@promise;
    }

    if (entry.translate)
        return entry.translate;

    var loader = this;
    var translatePromise = this.requestFetch(key).then(function (payload) {
        // Hook point.
        // 3. Loader.translate
        //     https://whatwg.github.io/loader/#browser-translate
        //     Take the key and the fetched source code and translate it to the ES6 source code.
        //     Typically it is used by the transpilers.
        return loader.translate(key, payload).then(function (source) {
            loader.setStateToMax(entry, loader.Instantiate);
            return source;
        });
    });
    entry.translate = translatePromise;
    return translatePromise;
}

function requestInstantiate(key)
{
    // https://whatwg.github.io/loader/#request-instantiate

    "use strict";

    var entry = this.ensureRegistered(key);
    if (entry.state > this.Link) {
        var deferred = @newPromiseCapability(@InternalPromise);
        deferred.@reject.@call(undefined, new @TypeError("Requested module is already ready to be executed."));
        return deferred.@promise;
    }

    if (entry.instantiate)
        return entry.instantiate;

    var loader = this;
    var instantiatePromise = this.requestTranslate(key).then(function (source) {
        // Hook point.
        // 4. Loader.instantiate
        //     https://whatwg.github.io/loader/#browser-instantiate
        //     Take the key and the translated source code, and instantiate the module record
        //     by parsing the module source code.
        //     It has the chance to provide the optional module instance that is different from
        //     the ordinary one.
        return loader.instantiate(key, source).then(function (optionalInstance) {
            loader.commitInstantiated(entry, optionalInstance, source);
            return entry;
        });
    });
    entry.instantiate = instantiatePromise;
    return instantiatePromise;
}

function requestResolveDependencies(key)
{
    // FIXME: In the spec, after requesting instantiation, we will resolve
    // the dependencies without any status change. As a result, when there
    // is circular dependencies, instantiation is done only once, but
    // repeatedly resolving the dependencies. This means that infinite
    // recursion occur when the given modules have circular dependency. To
    // avoid this situation, we introduce new state, "ResolveDependencies". This means
    // "Now the module is instantiated, so ready to resolve the dependencies
    // or now resolving them".
    // https://github.com/whatwg/loader/issues/68

    "use strict";

    var entry = this.ensureRegistered(key);
    if (entry.state > this.Link) {
        var deferred = @newPromiseCapability(@InternalPromise);
        deferred.@reject.@call(undefined, new @TypeError("Requested module is already ready to be executed."));
        return deferred.@promise;
    }

    if (entry.resolveDependencies)
        return entry.resolveDependencies;

    var loader = this;
    var resolveDependenciesPromise = this.requestInstantiate(key).then(function (entry) {
        var depLoads = [];
        for (var i = 0, length = entry.dependencies.length; i < length; ++i) {
            let pair = entry.dependencies[i];

            // Hook point.
            // 1. Loader.resolve.
            //     https://whatwg.github.io/loader/#browser-resolve
            //     Take the name and resolve it to the unique identifier for the resource location.
            //     For example, take the "jquery" and return the URL for the resource.
            var promise = loader.resolve(pair.key, key).then(function (depKey) {
                var depEntry = loader.ensureRegistered(depKey);

                // Recursive resolving. The dependencies of this entry is being resolved or already resolved.
                // Stop tracing the circular dependencies.
                // But to retrieve the instantiated module record correctly,
                // we need to wait for the instantiation for the dependent module.
                // For example, reaching here, the module is starting resolving the dependencies.
                // But the module may or may not reach the instantiation phase in the loader's pipeline.
                // If we wait for the ResolveDependencies for this module, it construct the circular promise chain and
                // rejected by the Promises runtime. Since only we need is the instantiated module, instead of waiting
                // the ResolveDependencies for this module, we just wait Instantiate for this.
                if (depEntry.resolveDependencies) {
                    return depEntry.instantiate.then(function (entry) {
                        pair.value = entry.module;
                        return entry;
                    });
                }

                return loader.requestResolveDependencies(depKey).then(function (entry) {
                    pair.value = entry.module;
                    return entry;
                });
            });
            @putByValDirect(depLoads, i, promise);
        }

        return @InternalPromise.internalAll(depLoads).then(function (modules) {
            loader.setStateToMax(entry, loader.Link);
            return entry;
        });
    });

    entry.resolveDependencies = resolveDependenciesPromise;
    return resolveDependenciesPromise;
}

function requestInstantiateAll(key)
{
    // https://whatwg.github.io/loader/#request-instantiate-all

    "use strict";

    return this.requestResolveDependencies(key);
}

function requestLink(key)
{
    // https://whatwg.github.io/loader/#request-link

    "use strict";

    var entry = this.ensureRegistered(key);
    if (entry.state > this.Link) {
        var deferred = @newPromiseCapability(@InternalPromise);
        deferred.@resolve.@call(undefined, entry.module);
        return deferred.@promise;
    }

    var loader = this;
    return this.requestInstantiateAll(key).then(function (entry) {
        loader.link(entry);
        return entry;
    });
}

function requestReady(key)
{
    // https://whatwg.github.io/loader/#request-ready

    "use strict";

    var loader = this;
    return this.requestLink(key).then(function (entry) {
        loader.moduleEvaluation(entry.module);
    });
}

// Linking semantics.

function link(entry)
{
    // https://whatwg.github.io/loader/#link

    "use strict";

    // FIXME: Current implementation does not support optionalInstance.
    // So Link's step 3 is skipped.
    // https://bugs.webkit.org/show_bug.cgi?id=148171

    if (entry.state === this.Ready)
        return;
    this.setStateToMax(entry, this.Ready);

    // Since we already have the "dependencies" field,
    // we can call moduleDeclarationInstantiation with the correct order
    // without constructing the dependency graph by calling dependencyGraph.
    var dependencies = entry.dependencies;
    for (var i = 0, length = dependencies.length; i < length; ++i) {
        var pair = dependencies[i];
        this.link(pair.value.registryEntry);
    }

    this.moduleDeclarationInstantiation(entry.module);
}

// Module semantics.

function moduleEvaluation(moduleRecord)
{
    // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation

    "use strict";

    if (moduleRecord.evaluated)
        return;
    moduleRecord.evaluated = true;

    var entry = moduleRecord.registryEntry;

    // The contents of the [[RequestedModules]] is cloned into entry.dependencies.
    var dependencies = entry.dependencies;
    for (var i = 0, length = dependencies.length; i < length; ++i) {
        var pair = dependencies[i];
        var requiredModuleRecord = pair.value;
        this.moduleEvaluation(requiredModuleRecord);
    }
    this.evaluate(moduleRecord);
}

function loadModule(moduleName, referrer)
{
    "use strict";

    var loader = this;
    // Loader.resolve hook point.
    // resolve: moduleName => Promise(moduleKey)
    // Take the name and resolve it to the unique identifier for the resource location.
    // For example, take the "jquery" and return the URL for the resource.
    return this.resolve(moduleName, referrer).then(function (key) {
        return loader.requestReady(key);
    });
}

function provide(key, stage, value)
{
    "use strict";

    var entry = this.ensureRegistered(key);

    if (stage === this.Fetch) {
        if (entry.status > this.Fetch)
            throw new @TypeError("Requested module is already fetched.");
        this.fulfillFetch(entry, value);
        return;
    }

    if (stage === this.Translate) {
        if (entry.status > this.Translate)
            throw new @TypeError("Requested module is already translated.");
        this.fulfillFetch(entry, undefined);
        this.fulfillTranslate(entry, value);
        return;
    }

    if (stage === this.Instantiate) {
        if (entry.status > this.Instantiate)
            throw new @TypeError("Requested module is already instantiated.");
        this.fulfillFetch(entry, undefined);
        this.fulfillTranslate(entry, value);
        var loader = this;
        entry.translate.then(function (source) {
            loader.fulfillInstantiate(entry, value, source);
        });
        return;
    }

    throw new @TypeError("Requested module is already ready to be executed.");
}
