package hu.swankey.ammo.common.yggdrasil.basics;

import hu.swankey.ammo.common.script.yunits.YClass;

import java.util.ArrayList;
import java.util.List;

public class YObject {

    public static final char DELIMITER = '.';
    
    public static final int ACCESS_LEVEL_PUBLIC = 1;
    public static final int ACCESS_LEVEL_PROTECTED = 2;
    public static final int ACCESS_LEVEL_PRIVATE = 3;
    
    /** Name of the element */
    private String name;
    
    /** Parent */
    protected YContainer container;
    
    /** Type */
    private YClass type;
    
    private int accessLevel = ACCESS_LEVEL_PUBLIC;
    
    public YObject(String name, YClass type) {
        setName(name);
        setType(type);
    }
    
    public static YClass yclass() {
    	return YClass.singleton();
    }
    
    
    /** Set the name of the element */
    public void setName(String newname) {
    	
        if (newname == null)
            throw new NullPointerException("Name cannot be null.");

        if (!newname.equals(getName())) {
        	String oldname = getName();
        	name = newname;

        	if (container != null)
        		container.reportRenamedElement(this, oldname);
        }
    }

    /** Get the name of the element */
    public String getName() {
        return name;
    }    
        
    
    /** Set the element's parent */
    protected void setParent(YContainer newParent) {
    	if (newParent == this)
    		throw new RuntimeException(newParent.toString()); //TODO: Ez ide nem kell. Vagy megcsinálni rendesen, teljes mélységben
        container = newParent;
    }
    
    /** Returns the parent of the element */
    public YContainer getContainer() {
        return container;
    }
   
    
    /** Returns the top container (if this is a simple element without parent, returns null) */
    public YObject getRoot() {
        if (container == null) 
            return this;
        else 
            return container.getRoot();
    }

    /** Get level (distance from root) */
    public int getLevel() {
        if (container == null)
            return 0;
        else
            return container.getLevel() + 1;
    }

    
    /** Return the path as an array of AbstractElements */
//    @Deprecated
//    public Element[] getPath() {
//        Element[] path = new Element[getLevel() + 1];
//        Element element = this;
//        while (element != null) {
//            path[element.getLevel()] = element;
//            element = (Element) element.getParent();
//        }
//        return path;
//    }
    
    public List<YObject> getPath(){
    	return getPathFrom(getRoot());
    }
    
    
    public List<YObject> getPathFrom(YObject element){    	
    	List<YObject> path;
    	
    	if (element == this)
    		path = new ArrayList<YObject>();    	
    	else  if (getContainer() == null || (path = getContainer().getPathFrom(element)) == null)
    		return null;
    		    	
    	path.add(this);    	
    	return path;
    }
    
    

    /** Return the path as a String */
    public String getPathString() {
    	
        if (container == null)
            return name;
        
        else return container.getPathString() + DELIMITER + name;
    }
    
    
    
    private void setType(YClass newtype){
        type = newtype;
    }
    
    public YClass getYClass(){
        return type;
    }
    
    

    @Override
    public String toString() {
        if (type != null)
            return getName() + " (" + getYClass().getName() + ")";
        else
            return getName();
    }
    

//    public boolean hasParent() {
//        return container != null;
//    }

    public boolean isRemovable() {
        return (container != null && container.isRemovable(this));
    }


	public int getAccessLevel() {
		return accessLevel;
	}
	
	public void setAccessLevel(int newLevel){
		accessLevel = newLevel;
	}
	
	public Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	


	public YObject copy() {
		throw new UnsupportedOperationException();
	}

}