/**
 * A `Dsymbol` representing a renamed import.
 *
 * Copyright:   Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
 * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
 * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dimport.d, _dimport.d)
 * Documentation:  https://dlang.org/phobos/dmd_dimport.html
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dimport.d
 */

module dmd.dimport;

import dmd.arraytypes;
import dmd.astenums;
import dmd.declaration;
import dmd.dmodule;
import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
import dmd.expression;
import dmd.globals;
import dmd.identifier;
import dmd.mtype;
import dmd.visitor;

/***********************************************************
 */
extern (C++) final class Import : Dsymbol
{
    /* static import aliasId = pkg1.pkg2.id : alias1 = name1, alias2 = name2;
     */
    Identifier[] packages;  // array of Identifier's representing packages
    Identifier id;          // module Identifier
    Identifier aliasId;
    int isstatic;           // !=0 if static import
    Visibility visibility;

    // Pairs of alias=name to bind into current namespace
    Identifiers names;
    Identifiers aliases;

    Module mod;
    Package pkg;            // leftmost package/module

    // corresponding AliasDeclarations for alias=name pairs
    AliasDeclarations aliasdecls;

    extern (D) this(const ref Loc loc, Identifier[] packages, Identifier id, Identifier aliasId, int isstatic)
    {
        Identifier selectIdent()
        {
            // select Dsymbol identifier (bracketed)
            if (aliasId)
            {
                // import [aliasId] = std.stdio;
                return aliasId;
            }
            else if (packages.length > 0)
            {
                // import [std].stdio;
                return packages[0];
            }
            else
            {
                // import [id];
                return id;
            }
        }

        super(loc, selectIdent());

        assert(id);
        version (none)
        {
            printf("Import::Import(");
            foreach (id; packages)
            {
                printf("%s.", id.toChars());
            }
            printf("%s)\n", id.toChars());
        }
        this.packages = packages;
        this.id = id;
        this.aliasId = aliasId;
        this.isstatic = isstatic;
        this.visibility = Visibility.Kind.private_; // default to private
    }

    extern (D) void addAlias(Identifier name, Identifier _alias)
    {
        if (isstatic)
            error("cannot have an import bind list");
        if (!aliasId)
            this.ident = null; // make it an anonymous import
        names.push(name);
        aliases.push(_alias);
    }

    override const(char)* kind() const
    {
        return isstatic ? "static import" : "import";
    }

    override Visibility visible() pure nothrow @nogc @safe
    {
        return visibility;
    }

    // copy only syntax trees
    override Import syntaxCopy(Dsymbol s)
    {
        assert(!s);
        auto si = new Import(loc, packages, id, aliasId, isstatic);
        si.comment = comment;
        for (size_t i = 0; i < names.dim; i++)
        {
            si.addAlias(names[i], aliases[i]);
        }
        return si;
    }

    /*******************************
     * Load this module.
     * Returns:
     *  true for errors, false for success
     */
    bool load(Scope* sc)
    {
        //printf("Import::load('%s') %p\n", toPrettyChars(), this);
        // See if existing module
        const errors = global.errors;
        DsymbolTable dst = Package.resolve(packages, null, &pkg);
        version (none)
        {
            if (pkg && pkg.isModule())
            {
                .error(loc, "can only import from a module, not from a member of module `%s`. Did you mean `import %s : %s`?", pkg.toChars(), pkg.toPrettyChars(), id.toChars());
                mod = pkg.isModule(); // Error recovery - treat as import of that module
                return true;
            }
        }
        Dsymbol s = dst.lookup(id);
        if (s)
        {
            if (s.isModule())
                mod = cast(Module)s;
            else
            {
                if (s.isAliasDeclaration())
                {
                    .error(loc, "%s `%s` conflicts with `%s`", s.kind(), s.toPrettyChars(), id.toChars());
                }
                else if (Package p = s.isPackage())
                {
                    if (p.isPkgMod == PKG.unknown)
                    {
                        uint preverrors = global.errors;
                        mod = Module.load(loc, packages, id);
                        if (!mod)
                            p.isPkgMod = PKG.package_;
                        else
                        {
                            // mod is a package.d, or a normal module which conflicts with the package name.
                            if (mod.isPackageFile)
                                mod.tag = p.tag; // reuse the same package tag
                            else
                            {
                                // show error if Module.load does not
                                if (preverrors == global.errors)
                                    .error(loc, "%s `%s` from file %s conflicts with %s `%s`", mod.kind(), mod.toPrettyChars(), mod.srcfile.toChars, p.kind(), p.toPrettyChars());
                                return true;
                            }
                        }
                    }
                    else
                    {
                        mod = p.isPackageMod();
                    }
                    if (!mod)
                    {
                        .error(loc, "can only import from a module, not from package `%s.%s`", p.toPrettyChars(), id.toChars());
                    }
                }
                else if (pkg)
                {
                    .error(loc, "can only import from a module, not from package `%s.%s`", pkg.toPrettyChars(), id.toChars());
                }
                else
                {
                    .error(loc, "can only import from a module, not from package `%s`", id.toChars());
                }
            }
        }
        if (!mod)
        {
            // Load module
            mod = Module.load(loc, packages, id);
            if (mod)
            {
                // id may be different from mod.ident, if so then insert alias
                dst.insert(id, mod);
            }
        }
        if (mod && !mod.importedFrom)
            mod.importedFrom = sc ? sc._module.importedFrom : Module.rootModule;
        if (!pkg)
        {
            if (mod && mod.isPackageFile)
            {
                // one level depth package.d file (import pkg; ./pkg/package.d)
                // it's necessary to use the wrapping Package already created
                pkg = mod.pkg;
            }
            else
                pkg = mod;
        }
        //printf("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
        return global.errors != errors;
    }

    override void importAll(Scope* sc)
    {
        if (mod) return; // Already done
        load(sc);
        if (!mod) return; // Failed

        if (sc.stc & STC.static_)
            isstatic = true;
        mod.importAll(null);
        mod.checkImportDeprecation(loc, sc);
        if (sc.explicitVisibility)
            visibility = sc.visibility;
        if (!isstatic && !aliasId && !names.dim)
            sc.scopesym.importScope(mod, visibility);
        // Enable access to pkgs/mod as soon as posible, because compiler
        // can traverse them before the import gets semantic (Issue: 21501)
        if (!aliasId && !names.dim)
            addPackageAccess(sc.scopesym);
    }

    /*******************************
     * Mark the imported packages as accessible from the current
     * scope. This access check is necessary when using FQN b/c
     * we're using a single global package tree.
     * https://issues.dlang.org/show_bug.cgi?id=313
     */
    extern (D) void addPackageAccess(ScopeDsymbol scopesym)
    {
        //printf("Import::addPackageAccess('%s') %p\n", toPrettyChars(), this);
        if (packages.length > 0)
        {
            // import a.b.c.d;
            auto p = pkg; // a
            scopesym.addAccessiblePackage(p, visibility);
            foreach (id; packages[1 .. $]) // [b, c]
            {
                p = cast(Package) p.symtab.lookup(id);
                // https://issues.dlang.org/show_bug.cgi?id=17991
                // An import of truly empty file/package can happen
                // https://issues.dlang.org/show_bug.cgi?id=20151
                // Package in the path conflicts with a module name
                if (p is null)
                    break;
                scopesym.addAccessiblePackage(p, visibility);
            }
        }
        scopesym.addAccessiblePackage(mod, visibility); // d
     }

    override Dsymbol toAlias()
    {
        if (aliasId)
            return mod;
        return this;
    }

    /*****************************
     * Add import to sd's symbol table.
     */
    override void addMember(Scope* sc, ScopeDsymbol sd)
    {
        //printf("Import.addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd.toChars(), sc);
        if (names.dim == 0)
            return Dsymbol.addMember(sc, sd);
        if (aliasId)
            Dsymbol.addMember(sc, sd);
        /* Instead of adding the import to sd's symbol table,
         * add each of the alias=name pairs
         */
        for (size_t i = 0; i < names.dim; i++)
        {
            Identifier name = names[i];
            Identifier _alias = aliases[i];
            if (!_alias)
                _alias = name;
            auto tname = new TypeIdentifier(loc, name);
            auto ad = new AliasDeclaration(loc, _alias, tname);
            ad._import = this;
            ad.addMember(sc, sd);
            aliasdecls.push(ad);
        }
    }

    override void setScope(Scope* sc)
    {
        Dsymbol.setScope(sc);
        if (aliasdecls.dim)
        {
            if (!mod)
                importAll(sc);

            sc = sc.push(mod);
            sc.visibility = visibility;
            foreach (ad; aliasdecls)
                ad.setScope(sc);
            sc = sc.pop();
        }
    }

    override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
    {
        //printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
        if (!pkg)
        {
            load(null);
            mod.importAll(null);
            mod.dsymbolSemantic(null);
        }
        // Forward it to the package/module
        return pkg.search(loc, ident, flags);
    }

    override bool overloadInsert(Dsymbol s)
    {
        /* Allow multiple imports with the same package base, but disallow
         * alias collisions
         * https://issues.dlang.org/show_bug.cgi?id=5412
         */
        assert(ident && ident == s.ident);
        Import imp;
        if (!aliasId && (imp = s.isImport()) !is null && !imp.aliasId)
            return true;
        else
            return false;
    }

    override inout(Import) isImport() inout
    {
        return this;
    }

    override void accept(Visitor v)
    {
        v.visit(this);
    }
}
