import java.util.Vector;
import java.io.*;
import java.awt.*;

public class EditConfig extends Panel implements FrameBufferInfo {

	private static final String test  = new String("  Test  ");
	private static final String accept = new String(" Accept ");
	private static final String cancel = new String(" Cancel ");
	private static final String warn_header = new String("\n"
			+  "                    *** WARNING ***                    \n");

	private static final String default_warning = new String(
			"\n fbconf cannot determine whether a selected resolution \n"
			+ " or frequency is supported by the attached monitor. \n"
			+ " In the event of a problem re-boot the machine and hold \n"
			+ " down the keys STOP (L-1) and N. This will reset the NVRAM.\n");

	private static final String need_monitor = new String(
			"\n This resolution cannot be obtained using any Sun supplied\n"
			+ " monitor. A third party product is required\n");

	private static final String not_supported = new String(
			"\n This resolution is not a supported configuration.\n"
			+ " It should work, but Sun Microsystems accepts \n"
			+ " no responsibility if it does not, and no support \n"
			+ " calls can be taken.");

	private static final String is_stereo = new String(
			"\n The resolution you have selected requires a STEREO display,\n"
			+ " and will not work on normal monitors.\n");
			
	private static final String is_interlaced = new String(
			"\n The resolution you have selected is interlaced for display\n"
			+ " on a PAL/NTSC TV and will not work on normal monitors.\n");
			
	fbconf parent;
	Configuration config;

	public EditConfig (fbconf f, Configuration conf) {
		parent = f;
		config = conf;

		Choice resolutions;
		int cols = 3;	// Number of editable items per fb
		int fbcount = config.fbcount();
		boolean console_set = false;

		setLayout(new BorderLayout());
		
		Panel editpanel = new Panel();
		GridBagLayout gridbag = new GridBagLayout();
		editpanel.setLayout(gridbag);

//	Actually we don't necessarily have the timing,
//	so this algorithm selects the highest frequency.
//	Is that a good idea, or should we go for the lowest?
//	Seems to work.

		CheckboxGroup consolegroup = new CheckboxGroup();
		Checkbox box;

		for (int c = 0; c < fbcount; c++) {
			Node node = config.node(c);
			Vector timing = new Vector();
			resolutions = new Choice();

			for (int i = 0; i < MAX_RES; i++) {
				if (node.supports(i)) {
					Timing tim = new Timing(i);
					String timestr = tim.identify();
					resolutions.add(timestr);
					if (i == 0)
						resolutions.select(timestr);
				}
			}

//	Assume that customer wants the default console
//	to be any non-SBUS frame buffer, eg SX or FFB
//	or (if none present) the first SBus card.

			if (console_set == true || node.is_sbus() == true)
				box = new Checkbox("", consolegroup, false);
			else {
				box = new Checkbox("", consolegroup, true);
				console_set = true;
			}
			node.set_edit_widgets(resolutions, box);
		}

		if (console_set == false) {
			box = config.node(0).get_consolebox();
			box.setState(true);
		}

//	Now update the panel

		GridBagConstraints constrain = new GridBagConstraints();
		constrain.weightx = 1.0;
		constrain.fill = GridBagConstraints.BOTH;
		constrain.gridwidth = 1;
		
		Label label;

		label = new Label("Frame Buffer");
		gridbag.setConstraints(label, constrain);
		editpanel.add(label);

		label = new Label("Preferred Resolution");
		gridbag.setConstraints(label, constrain);
		editpanel.add(label);

		constrain.gridwidth = GridBagConstraints.REMAINDER;
		label = new Label("Console");
		gridbag.setConstraints(label, constrain);
		editpanel.add(label);

		for (int c = 0; c < fbcount; c++) {
			Node n = config.node(c);
			label = new Label(n.get_fbtype() + "  " + n.identify());
			constrain.gridwidth = 1;
			gridbag.setConstraints(label, constrain);
			editpanel.add(label);

			resolutions = config.node(c).get_reschoice();
			gridbag.setConstraints(resolutions, constrain);
			editpanel.add(resolutions);

			constrain.gridwidth = GridBagConstraints.REMAINDER;
			box = config.node(c).get_consolebox();
			gridbag.setConstraints(box, constrain);
			editpanel.add(box);
		}

		Panel footer = new Panel();

//		Provide a function allowing the user to test the resolution
//		in order to verify that it is supported on the attached monitor.

//		footer.add(new Button(test));
		footer.add(new Button(accept));
		footer.add(new Button(cancel));

		setLayout(new BorderLayout());
		add("North", editpanel);
		add("South", footer);
	}

	public boolean handleEvent(Event ev) {
		String which = "";
		Timing tim = null;
		Node node = null;
		int count = config.fbcount();

		if (ev.id != Event.ACTION_EVENT)
			return(false);

		if (ev.target instanceof Button) {
			which = ((Button)ev.target).getLabel();
			if (which.equals(test)) { 
				System.out.println("Not Yet Implemented (sorry)");
				return true;
			} if (which.equals(accept)) { 
				String instr = new String("As root, execute the following commands: \n");
				String nvramrc = new String("probe-all\ninstall-console\nbanner\n");
				boolean use_nvram = false;

				for (int c = 0; c < count; c++) {
					node = config.node(c);
					tim = node.get_timing();
					if (node.is_console()) {
						if (tim.is_default()) {
							instr = instr + "\teeprom output-device=" + node.prompath() + "\n";
						} else {
							instr = instr + "\teeprom output-device=" + node.prompath() + ":r" + tim.promval() + "\n";
						}
					} else {
						if (tim.is_default())
							continue;

						String vsetup = new String("vsetup" + c + " ");
						String prompath = new String(" \" " + node.prompath() + "\" ");
						if (node.is_cgsix() && (tim.full_timing() != null)) {
							nvramrc = nvramrc + ": " + vsetup + "\" " + tim.full_timing() + "\" ;\n" +
								vsetup + node.get_sense_code() + prompath + "\" override\" execute-device-method drop \n";

						} else {
							nvramrc = nvramrc + "\" r" + tim.promval() + "\" " +prompath + "\" set-resolution\" execute-device-method drop\n";
						}
						use_nvram = true;
					}
				}
				instr = instr + "\teeprom use-nvramrc\\?=" + use_nvram + "\n";
				if (use_nvram) {
					instr = instr + "\teeprom nvramrc='" + nvramrc + "'" + "\n";
					instr = instr + "\teeprom fcode-debug\\?=true" + "\n";
				}
				instr = instr + "\nthen reboot the system\n";
				parent.showText(instr);
				return true;
			}
			else if (which.equals(cancel)) {
				hide();
				return true;
			}
		}
		else if (ev.target instanceof Choice) {

			which = ((Choice)ev.target).getSelectedItem();

findtime:	for (int c = 0; c < count; c++) {
				node = config.node(c);
				Choice ch = node.get_reschoice();

				if (ev.target.equals(ch)) {
					for (int i = 0; i < MAX_RES; i++) {
						tim = new Timing(i);
						if (which.equals(tim.identify())) {
							node.set_timing(tim);
							break findtime;
						}
					}
				}
			}

			if (tim == null)
				return false;

			String warn = new String("");

			if (tim.is_default() == false) {
				int to, def_xres = 0;

				if ((to = which.indexOf("x")) != -1)
					def_xres = Integer.parseInt(which.substring(0, to), 10);

				if (def_xres > 1280) {
					warn = warn + need_monitor;

//	Hi-res on SX works but isn't supported.

					if (node.is_type(SX))
						warn = warn + not_supported;
				}

				if (def_xres == 960)
					warn = warn + is_stereo;

				if (def_xres <= 770)
					warn = warn + is_interlaced;

				if (warn.length() == 0) 
					warn = default_warning;
			}
			parent.showText(warn_header +warn);
			return true;
		}
		return false;
	}

}
