package com.redhat.ceylon.compiler.loader;

import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;

import com.redhat.ceylon.compiler.js.CompilerErrorException;
import com.redhat.ceylon.compiler.typechecker.model.Module;

public class JsonModule extends Module {

    private Map<String,Object> model;
    private boolean loaded = false;

    public void setModel(Map<String, Object> value) {
        if (model != null) {
            final String modName = (String)model.get("$mod-name");
            final String modVers = (String)model.get("$mod-version");
            if (!(Objects.equals(modName, value.get("$mod-name"))
                    && Objects.equals(modVers, value.get("$mod-version")))) {
                throw new IllegalStateException("JsonModule " + modName+"/"+modVers
                        + " receives new module " + value.get("$mod-name")+"/"+value.get("$mod-version"));
            }
            return;
        }
        model = value;
    }
    public Map<String, Object> getModel() {
        return model;
    }

    void loadDeclarations() {
        if (loaded)return;
        if (model != null) {
            if (!loaded) {
                loaded=true;
                ArrayList<JsonPackage> pks = new ArrayList<>(model.size());
                for (Map.Entry<String, Object> e : model.entrySet()) {
                    if (!e.getKey().startsWith("$mod-")) {
                        JsonPackage p = new JsonPackage(e.getKey());
                        p.setModule(this);
                        pks.add(p);
                        getPackages().add(p);
                    }
                }
                for (JsonPackage p : pks) {
                    p.loadDeclarations();
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    public Map<String,Object> getModelForPackage(String name) {
        return model == null ? null : (Map<String,Object>)model.get(name);
    }

    @Override
    public com.redhat.ceylon.compiler.typechecker.model.Package getPackage(String name) {
        if ("default".equals(name)) {
            name = "";
        }
        final com.redhat.ceylon.compiler.typechecker.model.Package p = super.getPackage(name);
        if (p == null) {
            throw new CompilerErrorException("Package " + name + " not available");
        }
        return p;
    }

}

@@ -234,16 +234,82 @@
 .Module;
+%0Aimport com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
 %0A%0Apublic
@@ -2201,22 +2201,16 @@
         
-final 
 com.redh
@@ -2262,16 +2262,213 @@
 p = 
-super.ge
+getDirectPackage(name);%0A        if (p != null) %7B%0A            return p;%0A        %7D%0A        for (ModuleImport imp : getImports()) %7B%0A            final Module mod = imp.getModule();%0A            p = mod.getDirec
 tPac
@@ -2491,15 +2491,262 @@
     
+    
 if (p 
-=
+!= null) %7B%0A                return p;%0A            %7D%0A            for (ModuleImport im2 : mod.getImports()) %7B%0A                if (im2.isExport()) %7B%0A                    p = im2.getModule().getPackage(name);%0A                %7D%0A                if (p !
 = nu
@@ -2755,32 +2755,100 @@
 ) %7B%0A            
+  
+      return p;%0A                %7D%0A            %7D%0A        %7D%0A        
 throw new Compil
@@ -2903,38 +2903,28 @@
 able
-%22);%0A        %7D%0A        return p
+ in module %22 + this)
 ;%0A  

fix package search for #339