import java.util.*;

public class Space {

    final Map<String,Block> h = Collections.synchronizedMap(new TreeMap<String,Block>());
    private static Space space = new Space();

	private Space() {
	}
    
    public static Space getInstance()
    {
        return space;
    }

	public static double getTimestamp() {
		return (double) System.currentTimeMillis();
	}

	synchronized public void write (String name, Object value) {
        write(name,value,0,1.0f);
	}

	synchronized public void write (String name, Object value, double validity) {
        write(name,value,validity,1.0f);
	}

	synchronized public void write (String name, Object value, double validity, float priority) {
        if (validity > 0) validity += getTimestamp();
        Block block = h.get(name);
        if (block == null) {
            block = new Block(name,value,validity,priority);
            h.put(name,block);
        }
        else {
            if (priority >= block.getPriority())
                block.setValue(value,validity,priority);
        }
	}

	synchronized public Object read (String name) {
        return read(name,null);
	}

	synchronized public Object read (String name, Object deflt) {
        Block block = h.get(name);
		if (block == null) return deflt;
		else if (!valid(block,getTimestamp())) {
            block.setPriority(0f);
            return deflt;
        }
		else return block.getValue();
	}

	public boolean valid (Block block, double timestamp) {
        if (block.getValue() == null) return false;
		else if (block.getValidity() == 0) return true;
		else if (block.getValidity() < timestamp) return false;
		else return true;
	}

	public void registerTrigger (String name, Triggerable obj) {
        Block block = h.get(name);
		if (block == null) {
            block = new Block(name);
            h.put(name,block);
        }
		block.addTriggerable(obj);
	}

/*
    public static void delay (int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException ee) {
        }
    }
    
    public static void main(String[] args) {
        Space space1 = Space.getInstance();
        Space space2 = Space.getInstance();
        space1.write("ahoj","hoja");
        space2.write("leto","otel");
        System.out.println(space2.read("ahoj"));
        System.out.println(space1.read("leto"));
        space1.write("ahoj","hoja2");
        space2.write("leto","otel2");
        System.out.println(space1.read("ahoj"));
        System.out.println(space2.read("leto"));
        System.out.println("----");
        Triggerable agent = new Triggerable() {
            public void trigger() {
                System.out.println("TRIGGER");
            }
        };
        space1.registerTrigger("a",agent);
        space1.write("a","1",200);
        System.out.println((String) space1.read("a"));
        delay(100);
        System.out.println((String) space2.read("a"));
        delay(100);
        System.out.println((String) space1.read("a"));
        System.out.println("----");
        space2.write("a","x",200,2f);
        System.out.println((String) space1.read("a"));
        delay(100);
        space1.write("a","y",0,1f);
        System.out.println((String) space1.read("a"));
        delay(110);
        space1.write("a","y",0,1f);
        System.out.println((String) space1.read("a"));
    }
*/	

}
