package MapEditor;

import MapEditor.Brushes.*;
import MapEditor.Maps.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Set;
import javax.vecmath.*;

public final class MainWindow extends Frame implements ActionListener
{
	private IMapLoader m_loader = MapFileMEF.instance();	// by default, we load .mef map files
	private IMapSaver m_saver = MapFileMEF.instance();		// by default, we save maps as .mef files
	private Map m_map = new Map();
	private String m_mapFilename = "<Untitled Map>";		// the filename of the map we're currently editing
															// set to <Untitled Map> initially for new maps

	public MainWindow()
	{
		setTitle("GX Studios - Map Editor");
		setSize(Toolkit.getDefaultToolkit().getScreenSize());

		addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				System.exit(0);
			}
		});

		Panel toolbar = new Panel();
		toolbar.setBackground(Color.lightGray);
		toolbar.setLayout(new GridLayout(30,0,0,5));
		toolbar.add(new Label("Brush Type"));

		Button selectButton = new Button("Select");
		selectButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				m_map.set_state(Map.STATE_NORMAL);
			}
		});
		toolbar.add(selectButton);

		Button blockButton = new Button("Block");
		blockButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				m_map.set_state(Map.STATE_CREATE);
				m_map.set_brush_creation_type(Map.BRUSHCREATIONTYPE_BLOCK);
			}
		});
		toolbar.add(blockButton);

		Button cylinderButton = new Button("Cylinder");
		cylinderButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				m_map.set_state(Map.STATE_CREATE);
				m_map.set_brush_creation_type(Map.BRUSHCREATIONTYPE_CYLINDER);
			}
		});
		toolbar.add(cylinderButton);

		Button coneButton = new Button("Cone");
		coneButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				m_map.set_state(Map.STATE_CREATE);
				m_map.set_brush_creation_type(Map.BRUSHCREATIONTYPE_CONE);
			}
		});
		toolbar.add(coneButton);

		Button uvSphereButton = new Button("UV Sphere");
		uvSphereButton.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				m_map.set_state(Map.STATE_CREATE);
				m_map.set_brush_creation_type(Map.BRUSHCREATIONTYPE_UV_SPHERE);
			}
		});
		toolbar.add(uvSphereButton);

		Panel mainArea = new Panel();
		mainArea.setLayout(new GridLayout(2,2));

		DesignCanvas[] dcArr = new DesignCanvas[3];
		dcArr[0] = new DesignCanvas(m_map, new AxisPair(AxisPair.X,AxisPair.Y), 1, -1);
		dcArr[1] = new DesignCanvas(m_map, new AxisPair(AxisPair.X,AxisPair.Z), 1, -1);
		dcArr[2] = new DesignCanvas(m_map, new AxisPair(AxisPair.Y,AxisPair.Z), 1, -1);

		for(DesignCanvas dc: dcArr)
		{
			//for(DesignCanvas odc: dcArr) dc.add_repaint_listener(odc);
			m_map.add_repaint_listener(dc);
			mainArea.add(new AddScrollbars(dc));
		}

		mainArea.add(new DesignCanvas3D());

		Label statusbar = new Label("Status: ");
		statusbar.setBackground(Color.gray);

		setLayout(new BorderLayout());
		add("West", toolbar);
		add("Center", mainArea);
		add("South", statusbar);

		build_menus();
	}

	public void actionPerformed(ActionEvent e)
	{
		String ac = e.getActionCommand();
		if(ac.equals("File_New"))
		{
			m_map.replace_with(new Map());
			m_mapFilename = "<Untitled Map>";
		}
		else if(ac.equals("File_Load..."))
		{
			try
			{
				FileDialog dialog = new FileDialog(this, "Load", FileDialog.LOAD);
				dialog.setVisible(true);

				if(dialog.getFile() != null)
				{
					String filename = dialog.getDirectory() + dialog.getFile();
					m_map.replace_with(m_loader.load(filename));
					m_mapFilename = filename;	// if the load was a success, store the filename
				}
			}
			catch(IOException ex)
			{
				Util.message_box(this, "Error", "Could not load file: " + ex.getMessage());
			}
		}
		else if(ac.equals("File_Save") && !m_mapFilename.equals("<Untitled Map>"))
		{
// FIXME: Somehow make it obvious to the user that their file is being saved.
			m_saver.save(m_map, m_mapFilename);
		}
		else if(ac.equals("File_Save As...") || ac.equals("File_Save"))
		{
			FileDialog dialog = new FileDialog(this, "Save As...", FileDialog.SAVE);
			dialog.setVisible(true);

			if(dialog.getFile() != null)
			{
				// Prevent project-threatening accidents.
				if(dialog.getFile().endsWith(".java"))
				{
					Util.message_box(this, "Error", "Your less-than-cunning attempt to", "overwrite project source files",
													"has been thwarted by programmer", "foresight. Have a nice day!");
				}
				else
				{
					m_mapFilename = dialog.getDirectory() + dialog.getFile();
					m_saver.save(m_map, m_mapFilename);
				}
			}
		}
		else if(ac.equals("File_Exit"))
		{
			System.exit(0);
		}
		else if(ac.equals("Brush_Flip X"))
		{
			IBrush b = m_map.get_selected_brush();
			if(b instanceof ArchitectureBrush)
			{
				ArchitectureBrush ab = (ArchitectureBrush)b;
				ab.reflect(new Plane(new Vector3d(1,0,0), ab.centre().x));
				m_map.repaint();
			}
		}
		else if(ac.equals("Brush_Flip Y"))
		{
			IBrush b = m_map.get_selected_brush();
			if(b instanceof ArchitectureBrush)
			{
				ArchitectureBrush ab = (ArchitectureBrush)b;
				ab.reflect(new Plane(new Vector3d(0,1,0), ab.centre().y));
				m_map.repaint();
			}
		}
		else if(ac.equals("Brush_Flip Z"))
		{
			IBrush b = m_map.get_selected_brush();
			if(b instanceof ArchitectureBrush)
			{
				ArchitectureBrush ab = (ArchitectureBrush)b;
				ab.reflect(new Plane(new Vector3d(0,0,1), ab.centre().z));
				m_map.repaint();
			}
		}
		// TODO: All the other menu commands.
	}

	private void build_menus()
	{
		MenuBar mb = new MenuBar();
		setMenuBar(mb);

		Menu fileMenu = new Menu("File");
		String[] fileMenuItems = {"New","Load...","-","Save","Save As...","-","Exit"};
		for(String s: fileMenuItems)
		{
			MenuItem mi = new MenuItem(s);
			mi.setActionCommand("File_" + s);
			mi.addActionListener(this);
			fileMenu.add(mi);
		}
		mb.add(fileMenu);

		Menu mapMenu = new Menu("Map");
		String[] mapMenuItems = {"Compile...","-","Information..."};
		for(String s: mapMenuItems)
		{
			MenuItem mi = new MenuItem(s);
			mi.setActionCommand("Map_" + s);
			mi.addActionListener(this);
			mapMenu.add(mi);
		}
		mb.add(mapMenu);

		Menu brushMenu = new Menu("Brush");
		String[] brushMenuItems = {"Flip X","Flip Y","Flip Z"};
		for(String s: brushMenuItems)
		{
			MenuItem mi = new MenuItem(s);
			mi.setActionCommand("Brush_" + s);
			mi.addActionListener(this);
			brushMenu.add(mi);
		}
		mb.add(brushMenu);

		Menu optionsMenu = new Menu("Options");
		Set<String> options = m_map.get_option_set();
		for(final String s: options)
		{
			CheckboxMenuItem mi = new CheckboxMenuItem(s, m_map.option_set(s));
			mi.addItemListener(new ItemListener()
			{
				public void itemStateChanged(ItemEvent e)
				{
					switch(e.getStateChange())
					{
						case ItemEvent.DESELECTED:
							m_map.set_option(s, false);
							break;
						case ItemEvent.SELECTED:
							m_map.set_option(s, true);
							break;
					}
					m_map.repaint();
				}
			});
			optionsMenu.add(mi);
		}
		mb.add(optionsMenu);
	}

	public static void main(String args[]) throws IOException
	{
		MainWindow window = new MainWindow();
		window.setVisible(true);
	}
}
