package fr.umlv.talk.stackinterp2;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import fr.umlv.talk.Failure;

public class Klass extends Function {
  private final HashMap<String, Integer> fieldMap;
  private final HashMap<String, Function> methodMap = new HashMap<>();
  
  public static int HEADER_SIZE_IN_BYTES = 4;
  
  private Klass(String name, List<String> fields, HashMap<String, Integer> fieldMap) {
    super(name, fields, null);
    this.fieldMap = fieldMap;
  }
  
  static Klass createKlass(String name, List<String> fields) {
    int slot = HEADER_SIZE_IN_BYTES;
    HashMap<String, Integer> fieldMap = new HashMap<>();
    for(String field: fields) {
      fieldMap.put(field, slot);
      slot += 4;
    }
    return new Klass(name, fields, fieldMap);
  }
  
  @Override
  public String toString() {
    return getName() + ' ' + fieldMap + ' ' + getClass().getName() + '@' + hashCode();
  }
  
  public int getSizeInByte() {
    return HEADER_SIZE_IN_BYTES + fieldMap.size() << 2;
  }
  
  public int getFieldOffsetInByte(String name) {
    Integer offset = fieldMap.get(name);
    if (offset == null) {
      throw new Failure("no field " + name + " defined on klass " + getName());
    }
    return offset;
  }
  
  public Map<String,Function> getMethodMap() {
    return methodMap;
  }
  
  Set<String> fieldNames() {
    return fieldMap.keySet();
  }
}
