package kpc.common.computer;
import kawa.standard.Scheme;
import kpc.api.ComputerPosition;
import kpc.api.Signal;
import kpc.api.State;
import kpc.api.fs.FileSystem;
import kpc.api.fs.io.InputStream;
import kpc.common.computer.api.FileSystemApi;
import kpc.common.computer.api.PkgApi;
import kpc.common.computer.api.PrologApi;
import kpc.common.computer.api.TerminalApi;
import kpc.common.computer.fs.Ext9001FileSystem;
import kpc.common.kawa.get;
import kpc.common.kawa.gets;
import kpc.common.kawa.include;
import kpc.common.kawa.print;
import kpc.common.kawa.println;
import kpc.common.kawa.strings;
import kpc.common.utils.INBTTaggable;
import kpc.common.utils.SchemeFactory;
import net.minecraft.nbt.NBTTagCompound;
import java.io.InputStreamReader;
import java.util.concurrent.ForkJoinPool;
public final class Computer
implements kpc.api.computer.Computer,
INBTTaggable{
protected final ForkJoinPool threadPool;
protected final OperatingSystem os;
protected final Terminal terminal;
protected final Scheme scheme;
protected final FileSystem fs;
protected final ComputerPosition pos;
private State state = State.OFF;
public Computer(ComputerPosition pos, Terminal terminal){
this.terminal = terminal;
this.pos = pos;
this.fs = new Ext9001FileSystem();
this.os = new OperatingSystem(this);
this.threadPool = new ForkJoinPool();
this.scheme = SchemeFactory.create();
this.scheme.define("fs", new FileSystemApi(this.fs));
this.scheme.define("os", this.os);
this.scheme.define("term", new TerminalApi(this.terminal));
this.scheme.define("include", new include(this.fs));
this.scheme.define("prolog", new PrologApi(this.fs));
this.scheme.define("str", new strings());
this.scheme.define("pkg", new PkgApi(this));
this.scheme.defineFunction("print", new print(this.terminal));
this.scheme.defineFunction("println", new println(this.terminal));
this.scheme.defineFunction("gets", new gets(this.os, this.terminal));
this.scheme.defineFunction("get", new get(this.os, this.terminal));
}
@Override
public State state() {
return this.state;
}
@Override
public int id() {
return -1;
}
@Override
public void turnOn(){
if(this.state != State.RUNNING){
this.state = State.RUNNING;
this.terminal.clear();
this.terminal.setCursorPos(1, 1);
this.terminal.write("Loading Bios.scm");
this.threadPool.execute(
new Runnable() {
@Override
public void run() {
init();
}
}
);
}
}
@Override
public void shutdown() {
this.state = State.OFF;
}
@Override
public void reboot() {
this.state = State.OFF;
this.turnOn();
}
public void queueEvent(final String evnt, final Object... args){
this.threadPool.execute(
new Runnable() {
@Override
public void run() {
synchronized (this) {
Signal signal = new BasicSignal(evnt, args);
synchronized (os){
os.signal(signal);
}
}
}
}
);
}
@Override
public kpc.api.computer.Terminal terminal() {
return this.terminal;
}
@Override
public kpc.api.computer.OperatingSystem os() {
return this.os;
}
@Override
public Scheme scheme() {
return this.scheme;
}
@Override
public FileSystem fs() {
return this.fs;
}
@Override
public ComputerPosition pos() {
return this.pos;
}
private void init(){
try(InputStream stream = this.fs.openInputStream("/bios.scm")){
if(stream != null){
this.scheme.eval(new InputStreamReader(stream.toInputStream()));
} else{
throw new NullPointerException("Couldn't resolve bios.scm");
}
} catch(Throwable t){
this.terminal.clear();
this.terminal.setCursorPos(1, 1);
this.terminal.write("Error loading bios.scm");
this.terminal.setCursorPos(1, 2);
this.terminal.write("Message: " + t.getMessage());
t.printStackTrace(System.err);
}
}
@Override
public void readFromNBT(NBTTagCompound comp) {
NBTTagCompound c = comp.getCompoundTag("terminal");
this.terminal.readFromNBT(c);
this.state = State.valueOf(comp.getString("state") != null ? comp.getString("state") : "OFF");
}
@Override
public void writeToNBT(NBTTagCompound comp) {
NBTTagCompound c = new NBTTagCompound();
this.terminal.writeToNBT(c);
comp.setTag("terminal", c);
comp.setString("state", this.state.name());
}
}