package kpc.common.computer;
import kpc.api.Signal;
import kpc.api.driver.Driver;
import kpc.api.fs.io.InputStream;
import kpc.api.language.LanguageRegistry;
import kpc.api.language.LanguageRuntime;
import kpc.common.KPComputers;
import kpc.common.utils.ArgsParser;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public final class OperatingSystem
implements kpc.api.computer.OperatingSystem{
private final Queue<Signal> signalQueue = new LinkedList<>();
private final Lock readLock = new ReentrantLock();
private final Lock writeLock = new ReentrantLock();
private final kpc.api.computer.Computer computer;
protected OperatingSystem(Computer computer){
this.computer = computer;
}
public String version(){
return "v" + KPComputers.version;
}
public Object getDriver(String side){
TileEntity tile = this.computer.pos().tile(ForgeDirection.valueOf(side.toUpperCase()));
if(tile != null && tile instanceof Driver){
return tile;
} else{
return "No valid driver on side: " + side;
}
}
public Object[] stripArgs(Object[] args, int newIndex){
Object[] newArgs = new Object[args.length - newIndex];
System.arraycopy(args, newIndex, newArgs, 0, newArgs.length);
return newArgs;
}
public Object eval(String code){
try {
return this.computer.scheme().eval(code);
} catch (Throwable throwable) {
this.computer.terminal().clear();
this.computer.terminal().setCursorPos(1, 1);
this.computer.terminal().write("Error executing");
this.computer.terminal().setCursorPos(1, 2);
this.computer.terminal().write("Exception: " + throwable.getMessage());
throwable.printStackTrace(System.err);
return null;
}
}
public String getClipboard(){
try {
return (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
} catch (Exception e) {
return "";
}
}
public Object runScript(String ext, String exec){
String script = exec.contains(" ") ? exec.substring(0, exec.indexOf(' ')) : exec;
String[] args = exec.contains(" ") ? ArgsParser.parse(exec.substring(exec.indexOf(' ') + 1)) : null;
if(this.computer.fs().exists(script.trim() + ext)){
try(InputStream in = this.computer.fs().openInputStream(script.trim() + ext)){
LanguageRuntime runtime = LanguageRegistry.getLanguage(ext);
if(runtime == null){
throw new NullPointerException("Runtime == null");
}
return null;
} catch(Exception e){
return "Exception: " + e.getMessage();
}
}
if(this.computer.fs().exists("/bin/" + script.trim() + ext)){
try(InputStream in = this.computer.fs().openInputStream("/bin/" + script.trim() + ext)){
LanguageRuntime runtime = LanguageRegistry.getLanguage(ext);
if(runtime == null){
throw new NullPointerException("Runtime == null");
}
return null;
} catch(Exception e){
return "Exception: " + e.getMessage();
}
}
if(this.computer.fs().exists("/usr/bin/" + script.trim() + ext)){
try(InputStream in = this.computer.fs().openInputStream("/usr/bin/" + script.trim() + ext)){
LanguageRuntime runtime = LanguageRegistry.getLanguage(ext);
if(runtime == null){
throw new NullPointerException("Runtime == null");
}
return null;
} catch(Exception e){
return "Exception: " + e.getMessage();
}
}
return "Unable to locate: " + script.trim();
}
public Object runScheme(String execution){
String script = execution.contains(" ") ? execution.substring(0, execution.indexOf(' ')) : execution;
String[] args = execution.contains(" ") ? ArgsParser.parse(execution.substring(execution.indexOf(' ') + 1)) : null;
if(script.equals("bios.scm") || script.equals("/bios.scm")){
return "Cannot rerun bios.scm";
}
if(this.computer.fs().exists(script.trim() + ".scm")){
try(InputStream in = this.computer.fs().openInputStream(script.trim() + ".scm")){
this.computer.scheme().define("args", args);
Object ret = this.computer.scheme().eval(new InputStreamReader(in.toInputStream()));
this.computer.scheme().define("args", null);
if(ret != null){
return ret;
} else{
return null;
}
} catch(Throwable e){
return "Exception: " + e.getMessage();
}
}
if(this.computer.fs().exists("/bin/" + script.trim() + ".scm")){
try(InputStream in = this.computer.fs().openInputStream("/bin/" + script.trim() + ".scm")){
this.computer.scheme().define("args", args);
Object ret = this.computer.scheme().eval(new InputStreamReader(in.toInputStream()));
this.computer.scheme().define("args", null);
if(ret != null){
return ret;
} else{
return null;
}
} catch(Throwable e){
e.printStackTrace(System.err);
return "Exception: " + e.getMessage();
}
}
if(computer.fs().exists("/usr/bin/" + script.trim() + ".scm")){
try(InputStream in = this.computer.fs().openInputStream("/usr/bin/" + script.trim() + ".scm")){
this.computer.scheme().define("args", args);
Object ret = this.computer.scheme().eval(new InputStreamReader(in.toInputStream()));
this.computer.scheme().define("args", null);
if(ret != null){
return ret;
} else{
return null;
}
} catch(Throwable e){
e.printStackTrace(System.err);
return "Exception: " + e.getMessage();
}
}
return "Unable to locate: " + script;
}
public Signal pull(){
this.readLock.lock();
try{
while(this.signalQueue.isEmpty()){
synchronized(this){
this.wait();
}
}
return this.signalQueue.poll();
} catch(Exception e){
e.printStackTrace(System.err);
return new BasicSignal("__terminate__");
} finally{
this.readLock.unlock();
}
}
protected void signal(Signal signal){
this.writeLock.lock();
try{
this.signalQueue.add(signal);
this.notifyAll();
} finally{
this.writeLock.unlock();
}
}
public void signal(String name, Object... args){
this.writeLock.lock();
try{
this.signalQueue.add(new BasicSignal(name, args));
this.notifyAll();
} finally{
this.writeLock.unlock();
}
}
}