package edu.neu.ccs.demeterf.demfgen;

import edu.neu.ccs.demeterf.demfgen.classes.*;
import edu.neu.ccs.demeterf.lib.List;

public class ClassHier{
    public static List<FieldOrSyntax> superFieldsAndSyntax(List<String> dpars, List<InhrtPair> inhrt, String name){
        List<InhrtPair> extnd = inhrt.filter(new ClassGen.InhrtFor(name)).filter(new ClassGen.Extnds());
        if(extnd.isEmpty())return List.<FieldOrSyntax>create();
        InhrtPair sup = extnd.top();
        return (Diff.InhrtHelp.rebindFields(name, dpars, sup)
                .append(superFieldsAndSyntax(dpars, inhrt, sup.parent())));
    }
    public static List<Field> superFields(List<String> dpars, List<InhrtPair> inhrt, String name){
        return justFields(superFieldsAndSyntax(dpars, inhrt, name));
    }
    public static List<Field> justFields(List<FieldOrSyntax> flds){
        return flds.foldr(new List.Fold<FieldOrSyntax, List<Field>>(){
            public List<Field> fold(FieldOrSyntax fos, List<Field> fs){
                return fos.isSyntax()?fs:fs.push((Field)fos);
            }
        }, List.<Field>create());
    }
    
    public static TypeDef addSuperFields(TypeDef td, List<InhrtPair> inhrt){
        List<FieldOrSyntax> sfs = superFieldsAndSyntax(td.typeParams().toList(), inhrt, td.name());
        return td.addFieldsAndSyntax(sfs);
    }
    
    /** Represents the subtype relationship: child <: parent */
    public static class InhrtPair{
        InhrtStr inhrt;
        String chld;
        private List<TypeUse> uparams;
        public InhrtPair(InhrtStr pp, String cc, List<TypeUse> uparm){ inhrt = pp; chld = cc; uparams = uparm; }
        
        public String toString(){ return "["+chld+", "+inhrt+"]"; }
        public String parent(){ return inhrt.parent(); }
        public String child(){ return chld; }
        public String useParams(){ return uparams.isEmpty()?"":"<"+uparams.toString(",","")+">"; }
        public List<TypeUse> getUParams(){ return uparams; }
        
        public List<FieldOrSyntax> fields(){ return inhrt.fieldsAndSyntax(); }
        boolean extend(){ return inhrt.extend(); }
    }
    
    /** Represents the inheritence relationship "string", including inherited fields, and
     *    type parameters, but just the kind of relationship (extends or implements) */
    public static class InhrtStr{
        String parent;
        List<String> params;
        List<FieldOrSyntax> flds;
        public InhrtStr(String pp, List<String> dpar, List<FieldOrSyntax> fs)
        { parent = pp; params = dpar; flds = fs; }
        
        public List<FieldOrSyntax> fieldsAndSyntax(){ return flds; }
        boolean extend(){ return true; }
        public String parent(){ return parent; }
        /** TODO: This should not be used, just need to check before I delete it... */
        public String toString(){
            return (extend()?Diff.d.inherit:"implements")+" "+parent;
        }
    }
    
    public static class IntfcStr extends InhrtStr{
        public IntfcStr(String pp,  List<String> dpar){ super(pp,dpar,List.<FieldOrSyntax>create()); }
        boolean extend(){ return false; }
    }
}