package org.mozartoz.truffle.nodes.builtins;

import static org.mozartoz.truffle.nodes.builtins.Builtin.ALL;

import java.io.PrintStream;
import java.math.BigInteger;

import org.mozartoz.truffle.nodes.OzNode;
import org.mozartoz.truffle.nodes.builtins.VirtualStringBuiltins.ToAtomNode;
import org.mozartoz.truffle.nodes.builtins.VirtualStringBuiltinsFactory.ToAtomNodeFactory;
import org.mozartoz.truffle.runtime.OzCons;
import org.mozartoz.truffle.runtime.OzVar;
import org.mozartoz.truffle.runtime.Unit;

import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;

public abstract class SystemBuiltins {

	@Builtin(proc = true)
	@GenerateNodeFactory
	@NodeChild("value")
	public static abstract class ShowNode extends OzNode {

		@Specialization
		protected Object show(long value) {
			System.out.println(value);
			return unit;
		}

		@Specialization
		protected Object show(BigInteger value) {
			System.out.println(value);
			return unit;
		}

		@Specialization
		protected Object show(OzCons list) {
			System.out.println(list);
			return unit;
		}

		@Specialization
		protected Object show(OzVar var) {
			System.out.println(var);
			return unit;
		}

		@Specialization
		protected Object show(DynamicObject record) {
			System.out.println(record);
			return unit;
		}

		@Specialization
		protected Object show(Unit unit) {
			System.out.println(unit);
			return unit;
		}

		@Specialization
		protected Object show(String atom) {
			System.out.println(atom);
			return unit;
		}

		@Specialization(guards = "undefined == null")
		protected Object show(Object undefined) {
			System.out.println("null");
			return unit;
		}

	}

	@GenerateNodeFactory
	@NodeChildren({ @NodeChild("value"), @NodeChild("toStdErr") })
	public static abstract class PrintReprNode extends OzNode {

		@Specialization
		Object printRepr(Object value, Object toStdErr) {
			return unimplemented();
		}

	}

	@GenerateNodeFactory
	@NodeChildren({ @NodeChild("value"), @NodeChild("depth"), @NodeChild("width") })
	public static abstract class GetReprNode extends OzNode {

		@Specialization
		Object getRepr(Object value, Object depth, Object width) {
			return unimplemented();
		}

	}

	@GenerateNodeFactory
	@NodeChild("value")
	public static abstract class PrintNameNode extends OzNode {

		@Specialization
		Object printName(Object value) {
			return unimplemented();
		}

	}

	@Builtin(proc = true, deref = ALL)
	@GenerateNodeFactory
	@NodeChildren({ @NodeChild("value"), @NodeChild("toStdErr"), @NodeChild("newLine") })
	public static abstract class PrintVSNode extends OzNode {

		@Child ToAtomNode toAtomNode = ToAtomNodeFactory.create(null);

		@Specialization
		Object printVS(Object value, boolean toStdErr, boolean newLine) {
			String buffer = toAtomNode.executeToAtom(value);
			@SuppressWarnings("resource")
			PrintStream stream = toStdErr ? System.err : System.out;
			if (newLine) {
				stream.println(buffer);
			} else {
				stream.print(buffer);
				stream.flush();
			}
			return unit;
		}

	}

	@Builtin(proc = true)
	@GenerateNodeFactory
	public static abstract class GcDoNode extends OzNode {

		@Specialization
		Object gcDo() {
			return unimplemented();
		}

	}

	@GenerateNodeFactory
	@NodeChildren({ @NodeChild("lhs"), @NodeChild("rhs") })
	public static abstract class EqNode extends OzNode {

		@Specialization
		Object eq(Object lhs, Object rhs) {
			return unimplemented();
		}

	}

	@GenerateNodeFactory
	public static abstract class OnToplevelNode extends OzNode {

		@Specialization
		Object onToplevel() {
			return unimplemented();
		}

	}

	@GenerateNodeFactory
	@NodeChild("exitCode")
	public static abstract class ExitNode extends OzNode {

		@Specialization
		Object exit(Object exitCode) {
			return unimplemented();
		}

	}

}

@@ -134,37 +134,8 @@
 eam;
-%0Aimport java.math.BigInteger;
 %0A%0Aim
@@ -345,137 +345,8 @@
 ory;
-%0Aimport org.mozartoz.truffle.runtime.OzCons;%0Aimport org.mozartoz.truffle.runtime.OzVar;%0Aimport org.mozartoz.truffle.runtime.Unit;
 %0A%0Aim
@@ -544,60 +544,8 @@
 ion;
-%0Aimport com.oracle.truffle.api.object.DynamicObject;
 %0A%0Apu
@@ -751,847 +751,51 @@
 how(
-long value) %7B%0A%09%09%09System.out.println(value);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(BigInteger value) %7B%0A%09%09%09System.out.println(value);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(OzCons list) %7B%0A%09%09%09System.out.println(list);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(OzVar var) %7B%0A%09%09%09System.out.println(var);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(DynamicObject record) %7B%0A%09%09%09System.out.println(record);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(Unit unit) %7B%0A%09%09%09System.out.println(unit);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization%0A%09%09protected Object show(String atom) %7B%0A%09%09%09System.out.println(atom);%0A%09%09%09return unit;%0A%09%09%7D%0A%0A%09%09@Specialization(guards = %22undefined == null%22)%0A%09%09protected Object show(Object undefined) %7B%0A%09%09%09System.out.println(%22null%22
+Object value) %7B%0A%09%09%09System.out.println(value
 );%0A%09

simplify System.show