import java.io.*;
import java.awt.*;

class Node implements FrameBufferInfo {
	private String node;
	String family = "";
	int type_id = 0;
	int bus_slot = 0;
	int width = 0;
	int height = 0;
	int frequency = 0;
	int rev = 0;
	int memory = 0;
	int bit_depth = 0;
	int sense = 0;
	String resolution;
	boolean editable = false;
	Timing timing;
	String device_name;
	String dev_link;

//	The following are set up by the editor

	Choice res_choice;
	Checkbox console_box;

	private String getLine(String s) {
		int from = 0;
		int to = 0;

		if ((from = node.indexOf(s)) > -1) {
			if ((to = node.indexOf("\n", from)) > -1) {
				return(node.substring(from, to));
			}
		}
		return("");
	}

	Node(String s) {
		int i = 0;
		int from = 0;
		int to = 0;
		String tmp;

		this.node = s;

//	Get the family

		tmp = getLine("name:");
		if ((from = tmp.indexOf("'")) > -1) {
			if ((to = tmp.indexOf("'", from+1)) > -1) {

//	Strip off "SUNW," where present, eg leo

				if ((i = tmp.indexOf(",", from)) > -1)
					from = i;
						
				family = tmp.substring(from+1, to);
			}
		}

		tmp = getLine("vfreq:");
		if ((from = tmp.indexOf("0")) > -1)
			frequency = Integer.parseInt(tmp.substring(from), 16);
		

//	Get the SBus slot number - first numeric value in the reg: field

		tmp = getLine("reg:");
		if ((from = tmp.indexOf("0")) > -1) {
            if ((to = tmp.indexOf(".", from+1)) > -1) {
				bus_slot = Integer.parseInt(tmp.substring(from, to), 16);
			}
		}

//	Get the resolution: Width and Height

		tmp = getLine(" width:");
		if ((from = tmp.indexOf("0")) > -1)
			width = Integer.parseInt(tmp.substring(from), 16);

		tmp = getLine(" height:");
		if ((from = tmp.indexOf("0")) > -1)
			height = Integer.parseInt(tmp.substring(from), 16);

		if (family.equals("bwtwo")) {
			type_id = BWTWO;
			bit_depth = 1;
		} else 
		if (family.equals("cgthree")) {
			type_id = CG3;
			bit_depth = 8;

//	Actually CG3 has two options; 1152x900x66 and 1152x900x76.
//	The board will decide which to use based on the monitor sense code.
//	It makes no sense to configure this.

		} else 
		if (family.equals("cgsix")) {

//	Distinguish between (T)GX(+)

			type_id = GX;
			bit_depth = 8;

			tmp = getLine("chiprev:");
			if ((from = tmp.indexOf("0")) > -1) {
				rev = Integer.parseInt(tmp.substring(from), 16);
				if (rev == 11)
					type_id = TGX;
			}

			tmp = getLine("montype:");
			if ((from = tmp.indexOf("0")) > -1) {
				sense = Integer.parseInt(tmp.substring(from), 16);
			}

			tmp = getLine("vmsize:");
			if ((from = tmp.indexOf("0")) > -1) {
				memory = Integer.parseInt(tmp.substring(from), 16);
				switch (memory) {
					case 1:
						break;
					case 2:
						type_id = GX_2MB;
						break;
					case 4:
						type_id += (GXPLUS - GX);
						break;
					default:
						System.err.println("Error: GX can't have "+memory+"Mb!");
						break;
				}
			}
		} else 
		if (family.equals("cgtwelve")) {
			type_id = GS;
			bit_depth = 24;
		} else 

		if (family.equals("cgfourteen")) {
			type_id = SX;
			bit_depth = 24;
			tmp = getLine("reg:");
			if ((from = tmp.lastIndexOf(".")) > -1) {
				memory = Integer.parseInt(tmp.substring(from+1), 10) / 100000;
			}
		} else 

		if (family.equals("gt")) {
			type_id = GT;
			bit_depth = 24;
		} else 

		if (family.equals("leo")) {
			type_id = ZX;
			bit_depth = 24;
		} else 

		if (family.equals("tcx")) {
			tmp = getLine("tcx-8-bit:");
			if (tmp.equals("")) {
				type_id = S24;
				bit_depth = 24;
			} else {
				type_id = TCX;
				bit_depth = 8;
				tmp = getLine("vram:");
				if ((from = tmp.indexOf("0")) != -1) {
					memory = Integer.parseInt(tmp.substring(from+1), 10);
					if (memory == 2)
						type_id = TCX_2MB;
				}
			}
		} else 

		if (family.equals("ffb")) {
			bit_depth = 24;
			tmp = getLine("board_type:");
			if ((from = tmp.indexOf("0")) != -1) {
				switch (Integer.parseInt(tmp.substring(from+1), 16)) {
					case 8:
						type_id = FFB;
						rev = 67;
						memory = 5;
						break;
					case 11:
						type_id = CREATOR3D;
						rev = 67;
						memory = 5;
						break;
					case 27:
						type_id = CREATOR3D;
						rev = 75;
						memory = 15;
						break;
					case 32:
						type_id = FFB2_SV;
						memory = 5;
						break;
					case 35:
						type_id = FFB2_DV;
						memory = 15;
						break;
					case 64:
						type_id = FFB2_SH;
						memory = 5;
						break;
					case 67:
						type_id = FFB2_DH;
						memory = 15;
						break;
					default:
						type_id = UNKNOWN;
						break;
				}
			}
			tmp = getLine("upa-portid:");
			if ((from = tmp.indexOf("0")) != -1)
				bus_slot = Integer.parseInt(tmp.substring(from+1), 16);
			tmp = getLine("v_freq:");
			if ((from = tmp.indexOf("0")) > -1)
				frequency = Integer.parseInt(tmp.substring(from), 16);
		} else {
			type_id = UNKNOWN;
		}

		timing = new Timing(DEFAULT_RES);

//	Now get the device info from /etc/path_to_inst

		device_name = null;
		try {
			BufferedReader inst = new BufferedReader(
				new FileReader("/etc/path_to_inst"));
			String line;
			while ((line = inst.readLine()) != null) {
				if (line.indexOf(identify()) != -1) {
					int end = line.indexOf("\"", 1);
					int num = line.indexOf(" ", end+2);
					if (num == -1)
						num = line.length();

					device_name = new String("/devices" + line.substring(1, end) + ":" + family + line.substring(end+2, num));
					dev_link = new String("/dev/fbs/" + family + line.substring(end+2, num));
					break;
				}
			}
			inst.close();
		} catch (IOException e) {
			System.err.println(e);
		}
	}

	String get_description() {
		if (type_id > Description.length)
			type_id = Description.length;
		return(Description[type_id]);
	}

	String prompath() {
		String path = new String("/");

		switch (type_id) {
			case FFB:
			case CREATOR3D:
				break;
			case SX:
				path = path + "obio/";
                break;
			default:
				if (device_name.indexOf("iommu") != -1) {
					path = path + "iommu/";
				}
				path = path + "sbus/";
		}
		path = path + family + "@" + Integer.toString(bus_slot, 16);

		return(path);
	}

	String identify() {
		String id = new String (family + "@" + Integer.toString(bus_slot, 16));
		return id;
	}

	int get_avail_depth() {
		return bit_depth;
	}

	String get_fbtype() {
		return ID_STRING[type_id];
	}

	int memory() {
		return(memory);
	}

	String get_memory() {
		return (memory == 0) ? "Undetermined" : Integer.toString(memory);
	}

	void set_resolution(String res) {
		resolution = res;
	}

	String get_resolution() {
		if (resolution == null) {
			resolution = new String(width + "x" + height);
			if (frequency > 0)
				resolution = resolution + " @ " + frequency;
		}
		return resolution;
	}

	public boolean supports(int res) {
		return(Timing.supports(type_id, res));
	}

	public boolean is_cgsix() {
		switch(type_id) {
			case GX:
			case GXPLUS:
			case TGX:
			case TGXPLUS:
			case GX_2MB:
				return true;
			default:
				return false;
		}
	}

	public boolean is_sbus() {
		switch(type_id) {
			case FFB:
			case CREATOR3D:
			case SX:
			case TCX:	//	Well yes it is, but...
			case S24:	//	Well yes it is, but...
				return false;
			default:
				return true;
		}
	}

	public boolean is_type(int type) {
		return(type_id == type);
	}

	public boolean directcolor_24bit() {
		switch(type_id) {
			case ZX:
			case FFB:
			case CREATOR3D:
				return true;
			default:
				return false;
		}
	}

	public void set_edit_widgets(Choice res, Checkbox check) {
		res_choice = res;
		console_box = check;
		editable = true;
	}

	public Choice get_reschoice() {
		if (editable)
			return res_choice;
		else
			return null;
	}

	public Checkbox get_consolebox() {
		if (editable)
			return console_box;
		else
			return null;
	}

	public boolean is_console() {
		if (editable)
			return console_box.getState();
		else
			return false;
	}

	public void set_timing(Timing tim) {
		timing = tim;
	}

	public Timing get_timing() {
		return timing;
	}

	public int get_sense_code() {
		return sense;
	}

	public String devicename() {
		return dev_link;
	}
}
