package org.emerick.rtm.ui.lists;

import java.util.Vector;

import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.KeypadListener;
import net.rim.device.api.ui.ContextMenu;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.component.NullField;

import org.emerick.rtm.RTM;
import org.emerick.rtm.beans.Task;
import org.emerick.rtm.ui.field.FontColorField;
import org.emerick.rtm.ui.screens.DetailTaskScreen;


public class TaskListField extends ListField implements ListFieldCallback
{

	private Vector tasks;
	private Vector rows;
	private Bitmap p1;
	private Bitmap p2;
	private Bitmap p3;

	public TaskListField(Vector tasks)
	{
		super(0, ListField.MULTI_SELECT);
		setRowHeight(40);
		setEmptyString("Hooray, no tasks here!", DrawStyle.HCENTER);
		setCallback(this);
		setSearchable(false);

		p1 = Bitmap.getBitmapResource("p1.png");
		p2 = Bitmap.getBitmapResource("p2.png");
		p3 = Bitmap.getBitmapResource("p3.png");

		this.tasks = tasks;
		rows = new Vector();

		for (int x = 0; x < tasks.size(); ++x)
		{
			TableRowManager row = new TableRowManager();

			// SET THE PRIORITY BITMAP FIELD
			Task task = (Task)tasks.elementAt(x);

			switch (task.getPriority())
			{
			case 1:
				// if high priority, display p1 bitmap
				row.add(new BitmapField(p1));
				break;
			case 2:
				// if priority is 2, set p2 bitmap
				row.add(new BitmapField(p2));
				break;
			case 3:
				// if priority is 3, set p3 bitmap
				row.add(new BitmapField(p3));
				break;
			default:
				// no priority set
				row.add(new NullField());
				break;
			}

			// SET THE TASK NAME LABELFIELD
			// if overdue, bold/underline
			LabelField taskname = new LabelField(task.getName(), DrawStyle.ELLIPSIS);
			// if due today, bold
			if (task.overdue())
			{
				taskname.setFont(Font.getDefault().derive(Font.BOLD | Font.UNDERLINED));
			}
			else if (task.dueToday())
			{
				taskname.setFont(Font.getDefault().derive(Font.BOLD));
			}

			row.add(taskname);

			// SET THE LIST NAME
			row.add(new FontColorField(RTM.getListName(task.getListID()), DrawStyle.ELLIPSIS, 0x00878787));

			// SET THE DUE DATE/TIME
			row.add(new FontColorField(task.getFormattedDue(), DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
					| DrawStyle.RIGHT, 0x00878787));

			rows.addElement(row);
		}

		setSize(rows.size());
	}

	private class TableRowManager extends Manager
	{
		public TableRowManager()
		{
			super(0);
		}

		// Causes the fields within this row manager to be layed out then
		// painted.
		public void drawRow(Graphics g, int x, int y, int width, int height)
		{
			// Arrange the cell fields within this row manager.
			layout(width, height);

			// Place this row manager within its enclosing list.
			setPosition(x, y);

			// Apply a translating/clipping transformation to the graphics
			// context so that this row paints in the right area.
			g.pushRegion(getExtent());

			// Paint this manager's controlled fields.
			subpaint(g);

			g.setColor(0x00CACACA);
			g.drawLine(0, 0, getPreferredWidth(), 0);
			g.drawLine(10, 0, 10, getPreferredHeight());

			// Restore the graphics context.
			g.popContext();
		}

		// Arrages this manager's controlled fields from left to right within
		// the enclosing table's columns.
		protected void sublayout(int width, int height)
		{
			// set the size and position of each field.
			int fontHeight = Font.getDefault().getHeight();
			int preferredWidth = getPreferredWidth();

			// start with the Bitmap Field of the priority icon
			Field field = getField(0);
			layoutChild(field, 10, 40);
			setPositionChild(field, 0, 0);

			// set the task name label field
			field = getField(1);
			layoutChild(field, preferredWidth - 16, fontHeight + 1);
			setPositionChild(field, 16, 3);

			// set the list name label field
			field = getField(2);
			layoutChild(field, 150, fontHeight + 1);
			setPositionChild(field, 16, fontHeight + 6);

			// set the due time name label field
			field = getField(3);
			layoutChild(field, 150, fontHeight + 1);
			setPositionChild(field, preferredWidth - 152, fontHeight + 6);

			setExtent(preferredWidth, getPreferredHeight());
		}

		// The preferred width of a row is defined by the list renderer.
		public int getPreferredWidth()
		{
			return Graphics.getScreenWidth();
		}

		// The preferred height of a row is the "row height" as defined in the
		// enclosing list.
		public int getPreferredHeight()
		{
			return getRowHeight();
		}
	}

	// ListFieldCallback Implementation
	public void drawListRow(ListField listField, Graphics g, int index, int y, int width)
	{
		TaskListField list = (TaskListField) listField;
		TableRowManager rowManager = (TableRowManager) list.rows.elementAt(index);
		rowManager.drawRow(g, 0, y, width, list.getRowHeight());
	}

	public Object get(ListField list, int index)
	{
		return tasks.elementAt(index);
	}

	public int indexOfList(ListField list, String prefix, int start)
	{
		for(int x = start; x < tasks.size(); ++x)
		{
			Task task = (Task)tasks.elementAt(x);
			if(task.getName().startsWith(prefix))
			{
				return x;
			}
		}
		return -1;
	}

	public int getPreferredWidth(ListField list)
	{
		return Graphics.getScreenWidth();
	}

	public ContextMenu getContextMenu()
	{
		ContextMenu menu = super.getContextMenu();

		menu.addItem(new CompleteTaskMenuItem());
		menu.addItem(new EditTaskMenuItem());
		menu.addItem(new DeleteTaskMenuItem());
		menu.addItem(new PostponeTaskMenuItem());

		return menu;
	}

	protected boolean navigationClick(int status, int time)
	{
		if ((status & KeypadListener.STATUS_TRACKWHEEL) == KeypadListener.STATUS_TRACKWHEEL)
			return false;

		selectItem();

		return true;
	}

	protected boolean keyDown(int keycode, int time)
	{
		if (Keypad.key(keycode) == Keypad.KEY_ENTER)
		{
			selectItem();
		}
		else if (Keypad.key(keycode) == Keypad.KEY_DELETE)
		{
			deleteSelected();
		}
		else if (Keypad.map(keycode) == 'c')
		{
			completeSelected();
		}
		else if (Keypad.map(keycode) == 'p')
		{
			postponeSelected();
		}
		else if(Keypad.map(keycode) == 't')
		{
			setSelectedIndex(0);
			setFocus();
		}
		else if(Keypad.map(keycode) == 'b')
		{
			setSelectedIndex(tasks.size() - 1);
			setFocus();
		}
		else
		{
			return false;
		}
		return true;
	}

	public void delete(int index)
	{		
		super.delete(index);
		tasks.removeElementAt(index);
	}

	public void selectItem()
	{
		int index = getSelectedIndex();

		UiApplication.getUiApplication().pushScreen(new DetailTaskScreen((Task)tasks.elementAt(index)));
	}

	public void completeSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.completeTask((Task)tasks.elementAt(items[x - 1]));
			delete(items[x - 1]);
		}
	}

	public void deleteSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.deleteTask((Task)tasks.elementAt(items[x - 1]));
			delete(items[x - 1]);
		}
	}

	public void postponeSelected()
	{
		int[] items = getSelection();
		for (int x = items.length; x > 0; x--)
		{
			RTM.postponeTask((Task)tasks.elementAt(items[x - 1]));
			((Task)tasks.elementAt(items[x - 1])).postpone();
		}
	}

	private final class CompleteTaskMenuItem extends MenuItem
	{
		public CompleteTaskMenuItem()
		{
			super("Complete", 100000, 1);
		}

		public void run()
		{
			completeSelected();
		}
	}

	private final class EditTaskMenuItem extends MenuItem
	{
		public EditTaskMenuItem()
		{
			super("Edit", 100001, 2);
		}

		public void run()
		{
			selectItem();
		}
	}

	private final class DeleteTaskMenuItem extends MenuItem
	{
		public DeleteTaskMenuItem()
		{
			super("Delete", 100002, 3);
		}

		public void run()
		{
			deleteSelected();
		}
	}

	private final class PostponeTaskMenuItem extends MenuItem
	{
		public PostponeTaskMenuItem()
		{
			super("Postpone", 100004, 4);
		}

		public void run()
		{
			postponeSelected();
		}
	}

}