package org.wikiwebserver.distribute.server;

import org.wikiwebserver.distribute.interfaces.Generator;
import org.wikiwebserver.distribute.interfaces.Processor;
import org.wikiwebserver.distribute.interfaces.Task;
import org.wikiwebserver.distribute.interfaces.Transferer;
import org.wikiwebserver.distribute.interfaces.WorkerNode;
import org.wikiwebserver.distribute.se.ConfigManager;

import page.tools.entity.NodeData;
import page.tools.entity.User;

public class LocalWorkerNode implements WorkerNode {
	
	public static final int TASK_EXPIRE_DELAY = 30 * 1000;
	
	private NodeData nodeData;
	private String nodeId;
	private String configurationId = "STATIC";
	
	public LocalWorkerNode(String nodeId, String name) {
		this.nodeId = nodeId;
		nodeData = NodeData.getNodeDataById(nodeId);
		if (nodeData == null) {
            nodeData = new NodeData(nodeId);
            nodeData.put("createdTime", new Long(System.currentTimeMillis()));	
		}
		
        nodeData.setName(name);
        nodeData.put("osName", System.getProperty("os.name"));
        nodeData.setRequiresPassword(false);
        
        User mike = User.getUserByEmail("mike" + "@" + "wikiwebserver.org");
        if (mike != null) {
            nodeData.setOwner(mike);	
        }
	}
	
	public String getNodeId() {
		return this.nodeId;
	}
	
	public String getConfigurationId() {
		return this.configurationId;
	}		
	
	public int getWaitTime() {
		return 0;
	}

	public TaskStub addNewTaskAndWait(final Task task) throws Exception {
	    
	    ConfigManager.setString("nodePath", "example_node");
		
		long time = System.currentTimeMillis();	
		if (task.getExpireTime() == 0) {
			task.setExpireTime(time + TASK_EXPIRE_DELAY);
		}
		
		final TaskStub stub = new TaskStub(task);
		
		if (task instanceof Runnable) {
			((Runnable) task).run();
		}
		else if (task instanceof Transferer) {
			
			if (task instanceof Generator) {
			    Object output = ((Generator)task).generate();
                stub.setTaskOutputMeta(task.getTaskOutputMeta());			    
				stub.setOutput(output);
			}
			
			if (task instanceof Processor) {
				Runnable processor = new Runnable() {
					public void run() {
						if (stub.getInput() == null) {
							synchronized (stub) {
								try {
									stub.wait(TASK_EXPIRE_DELAY);
								} catch (InterruptedException ex) {
									ex.printStackTrace();
								}
							}
						}
						try {
							((Processor)task).process(stub.getInput());
						} catch (Exception ex) {
							ex.printStackTrace();
						}
					}
				};
				new Thread(processor).start();
			}
		}
		
		nodeData.incrementValue("numTasksAssigned", 1);
		
		return stub;
	}

    public void reduceWaitTime() {

    }	
}

