using System;
using System.Data;
using System.Web.UI.MobileControls;
using System.Configuration;
using ASPNET.StarterKit.TimeTracker.BusinessLogicLayer;

namespace ASPNET.StarterKit.TimeTracker.MobileWeb
{
	//*********************************************************************
	//
	//	TimeSheet.aspx
	//
	//	The TimeSheet.aspx page is the mobile version of the Time Tracker application.
	//	This page contains all the required mobile forms to view, update, and insert
	//	time entries.
	//
	//	Hidden fields are used to preserve state between requests.  These hidden fields
	//	can be found in FormDetail.
	//
	//*********************************************************************

	public class TimeSheet : System.Web.UI.MobileControls.MobilePage
	{
		protected System.Web.UI.MobileControls.Label WeekEndingMain;
		protected System.Web.UI.MobileControls.ObjectList TimeEntryGrid;
		protected System.Web.UI.MobileControls.Label WeekEndingDetail;
		protected System.Web.UI.MobileControls.Label ProjectLabel;
		protected System.Web.UI.MobileControls.Label CategoryLabel;
		protected System.Web.UI.MobileControls.SelectionList CategoryList;
		protected System.Web.UI.MobileControls.Label DayLabel;
		protected System.Web.UI.MobileControls.SelectionList DayList;
		protected System.Web.UI.MobileControls.Label HoursLabel;
		protected System.Web.UI.MobileControls.TextBox HoursText;
		protected System.Web.UI.MobileControls.Label EntryDescriptionLabel;
		protected System.Web.UI.MobileControls.TextBox EntryDescriptionText;
		protected System.Web.UI.MobileControls.Command SaveCommand;
		protected System.Web.UI.MobileControls.Command CancelCommand;
		protected System.Web.UI.MobileControls.Form FormDetail;
		protected System.Web.UI.MobileControls.Form FormProject;
		protected System.Web.UI.MobileControls.Label Label1;
		protected System.Web.UI.MobileControls.SelectionList ProjectListBox;
		protected System.Web.UI.MobileControls.Command SelectProjectCommand;
		protected System.Web.UI.MobileControls.Command ChangeProjectCommand;
		protected System.Web.UI.MobileControls.Form FormCalendar;
		protected System.Web.UI.MobileControls.Calendar Calendar1;
		protected System.Web.UI.MobileControls.Command ChangeWeekDetail;
		protected System.Web.UI.MobileControls.Command ChangeWeekMain;
		protected System.Web.UI.MobileControls.Label TotalHoursLabel;
		protected System.Web.UI.MobileControls.Command AddEntryCommand2;
		protected System.Web.UI.MobileControls.Form FormMain;
		protected System.Web.UI.MobileControls.RequiredFieldValidator RequiredFieldValidatorHrs;
		protected System.Web.UI.MobileControls.RequiredFieldValidator RequiredFieldValidatorDesc;
		protected System.Web.UI.MobileControls.CompareValidator CompareValidatorHrs;
		protected System.Web.UI.MobileControls.StyleSheet Stylesheet1;
		protected System.Web.UI.MobileControls.Label Title;
		protected System.Web.UI.MobileControls.DeviceSpecific DeviceSpecific2;
		protected System.Web.UI.MobileControls.Panel Panel2;
		protected System.Web.UI.MobileControls.Label Label2;
		protected System.Web.UI.MobileControls.Label Label3;
		protected System.Web.UI.MobileControls.Label Label4;
		protected System.Web.UI.MobileControls.Label HiddenProjectName;
		protected System.Web.UI.MobileControls.Label HiddenProjectID;
		protected System.Web.UI.MobileControls.Label HiddenLogID;
		protected System.Web.UI.MobileControls.Label HiddenDate;
		protected System.Web.UI.MobileControls.Label HiddenOrigin;

		private TimeEntry _entryHolder = new TimeEntry();		// User's input holder
		private TTUser _user;
		private DateTime _weekEndingDate = DateTime.MinValue;
		private DateTime _weekStartingDate = DateTime.MinValue;
		protected System.Web.UI.MobileControls.Command DeleteCommand;
		private decimal _totalHours = decimal.Zero;
		
		private enum FormName {
			FormMain, FormDetail
		}

		private void Page_Load(object sender, System.EventArgs e)
		{
			_user = new TTUser(
				TTSecurity.GetUserID(),
				User.Identity.Name,
				TTSecurity.GetName(),
				TTSecurity.GetUserRole());

			if (!IsPostBack) 
			{
				_entryHolder.EntryDate = DateTime.Today;
				HiddenDate.Text = DateTime.Today.ToShortDateString();
			}
			else
			{
				// Try to get state information from hidden fields
				_entryHolder.EntryDate = Convert.ToDateTime(HiddenDate.Text);
				if (CategoryList.Selection != null) _entryHolder.CategoryID = Convert.ToInt32(CategoryList.Selection.Value);
				_entryHolder.Description = TTSecurity.CleanStringRegex(EntryDescriptionText.Text);
				
				// If there is error during retrieving state, then ignore.
				try
				{
					_entryHolder.ProjectID = Convert.ToInt32(HiddenProjectID.Text);
					_entryHolder.EntryLogID = Convert.ToInt32(HiddenLogID.Text);
					_entryHolder.ProjectName = TTSecurity.CleanStringRegex(HiddenProjectName.Text);
					_entryHolder.Duration = Convert.ToDecimal(HoursText.Text);
				} 
				catch {}
			}
		}
		
		//*********************************************************************
		//
		//	FormMain is the main form for this web application.  From this form, user
		//	can view their time entries by the week and select whether to update or add
		//	an entry.
		//
		//*********************************************************************

		private void FormMain_Activate(object sender, System.EventArgs e)
		{
			TimeEntry.FillCorrectStartEndDates(_entryHolder.EntryDate, ref _weekStartingDate, ref _weekEndingDate);
			TotalHoursLabel.Text = "Total Hours: 0";
			WeekEndingMain.Text = "Week Ending: " + _weekEndingDate.ToShortDateString() + "  ";
			BindTimeSheet(TimeEntryGrid, _user.UserID, _weekStartingDate, _weekEndingDate);	
		}

		//*********************************************************************
		//
		//	This event fires when users click to view an entry detail.  The selected
		//	EntryLogID can be determined from the selected ListItem and be used to 
		//	load the correct Entry Log.  
		//
		//*********************************************************************

		private void TimeEntryGrid_Select(object sender, System.Web.UI.MobileControls.ObjectListSelectEventArgs e)
		{
			// Load a new TimeEntry object based on selected EntryLogID
			int currentEntryLogID = Convert.ToInt32(e.ListItem["EntryLogID"]);
			_entryHolder = new TimeEntry(currentEntryLogID);
			_entryHolder.Load();

			ActiveForm = FormDetail;
		}

		//*********************************************************************
		//
		//	This event fires when an item from the DataSource is binded to the grid.
		//	Calculating the total hours is done here since this event evaluates 
		//	each item from the DataSource.
		//
		//*********************************************************************

		private void TimeEntryGrid_ItemBind(object sender, System.Web.UI.MobileControls.ObjectListDataBindEventArgs e)
		{
			// Calculate total hours for this week and display
			_totalHours += ((TimeEntry)e.DataItem).Duration;
			TotalHoursLabel.Text = "Total Hours: " + _totalHours.ToString();
		}

		private void ChangeWeekMain_Click(object sender, System.EventArgs e)
		{
			// Preserve the originated form before opening the calendar
			HiddenOrigin.Text = FormName.FormMain.ToString();
			ActiveForm = FormCalendar;
		}

		protected void AddEntryCommand2_Click(object sender, System.EventArgs e)
		{
			ActiveForm = FormProject;
		}

		//*********************************************************************
		//
		//	FormProject is used to select which project to select for the specific
		//	time entry.  The ProjectListBox is filled with all the projects that the
		//	user is allow to view.
		//
		//*********************************************************************

		private void FormProject_Activate(object sender, System.EventArgs e)
		{
			ProjectsCollection dsProject = BindProjectList(ProjectListBox, _user.UserID);			

			// Set default for Project ID and save it to Session
			//If update, ProjectID should be set from Session 
			//If insert, select the first ProjectID from collection
			//If user not a member of any project, then dsProject will be null
			if (_entryHolder.ProjectID==0 && dsProject.Count>0)
				_entryHolder.ProjectID = ((Project)dsProject[0]).ProjectID;
			// Otherwise, keep _entryHolder.ProjectID the same

			//Everytime ProjectList is bound, then find the correct index for it
			if (null != dsProject) ProjectListBox.SelectedIndex = FindProjectIndex(ProjectListBox, _entryHolder.ProjectID);
		}

		private void SelectProjectCommand_Click(object sender, System.EventArgs e)
		{
			// When FormProject is activated, there is ALWAYS a default selection 
			if (null == ProjectListBox.Selection) 
			{
				// User is not a member of any project, return to main form
				ActiveForm = FormMain;
			}
			else 
			{
				// Save user's selection and proceed
				HiddenProjectID.Text = ProjectListBox.Selection.Value;
				_entryHolder.ProjectID = Convert.ToInt32(ProjectListBox.Selection.Value);
				HiddenProjectName.Text = TTSecurity.CleanStringRegex(ProjectListBox.Selection.Text);
				_entryHolder.ProjectName = TTSecurity.CleanStringRegex(ProjectListBox.Selection.Text);
				ActiveForm = FormDetail;
			}
		}
	
		//*********************************************************************
		//
		//	FormDetail is where the user can view a specific entry in detail during 
		//	update mode.  This form can also be used to insert a new time entry.
		//
		//	This form has some hidden fields to preserve state between requests.
		//
		//*********************************************************************

		private void FormDetail_Activate(object sender, System.EventArgs e)
		{
			TimeEntry.FillCorrectStartEndDates(_entryHolder.EntryDate, ref _weekStartingDate, ref _weekEndingDate);
			BindCategoryList(CategoryList, _entryHolder.ProjectID, _entryHolder.CategoryID);
			
			if (_entryHolder.EntryLogID == 0)
			{
				// This is an insert since EntryLogID is not assigned, use today's day for 
				// default DayList's selected index
				BindDayList(DayList, _entryHolder.EntryDate, DateTime.Today);
				DeleteCommand.Visible = false;
			}
			else
			{
				BindDayList(DayList, _entryHolder.EntryDate, _entryHolder.EntryDate);
				DeleteCommand.Visible = true;
			}

			WeekEndingDetail.Text = "Week Ending: " + _weekEndingDate.ToShortDateString() + "  ";
			PopulateFormDetail(_entryHolder);
		}
		
		private void ChangeWeekDetail_Click(object sender, System.EventArgs e)
		{
			// Remember the originated form before opening the calendar
			HiddenOrigin.Text = FormName.FormDetail.ToString();
			ActiveForm = FormCalendar;
		}

		private void ChangeProjectCommand_Click(object sender, System.EventArgs e)
		{
			ActiveForm = FormProject;
		}

		private void SaveCommand_Click(object sender, System.EventArgs e)
		{
			RequiredFieldValidatorHrs.Validate();
			RequiredFieldValidatorDesc.Validate();
			CompareValidatorHrs.Validate();

			if (RequiredFieldValidatorHrs.IsValid && RequiredFieldValidatorDesc.IsValid && CompareValidatorHrs.IsValid)
			{
				// Update User's Input since drop down list won't fire an event until post back
				// This is the time to catch any date changes.
				_entryHolder.EntryDate = Convert.ToDateTime(DayList.Selection.Value);
				
				TimeEntry time = new TimeEntry(_entryHolder.EntryLogID, _user.UserID, _entryHolder.ProjectID, _entryHolder.CategoryID, _entryHolder.EntryDate, _entryHolder.Description, _entryHolder.Duration);
				time.Save();

				// Reset _entryHolder for Session
				_entryHolder = new TimeEntry();
				_entryHolder.EntryDate = Convert.ToDateTime(DayList.Selection.Value);

				// Reset Form Detail
				PopulateFormDetail(_entryHolder);
				ActiveForm = FormMain;
			}
		}

		private void DeleteCommand_Click(object sender, System.EventArgs e)
		{
			TimeEntry.Remove(_entryHolder.EntryLogID);

			// Reset _entryHolder for Session
			_entryHolder = new TimeEntry();
			_entryHolder.EntryDate = Convert.ToDateTime(DayList.Selection.Value);

			// Reset Form Detail
			PopulateFormDetail(_entryHolder);
			ActiveForm = FormMain;
		}

		private void CancelCommand_Click(object sender, System.EventArgs e)
		{
			// Reset _entryHolder for Session
			_entryHolder = new TimeEntry();
			_entryHolder.EntryDate = Convert.ToDateTime(DayList.Selection.Value);

			// Reset Form Detail
			PopulateFormDetail(_entryHolder);
			ActiveForm = FormMain;
		}
		
		//*********************************************************************
		//
		//	FormCalendar is used from two forms: FormMain and FormDetail.  Change
		//	FirstDayOfWeek key in web.config file to change the Calendar display
		//	through out this application.
		//
		//*********************************************************************

		private void FormCalendar_Activate(object sender, System.EventArgs e)
		{
			int configFirstDay = Convert.ToInt32(ConfigurationSettings.AppSettings[Global.CfgKeyFirstDayOfWeek]);
			Calendar1.FirstDayOfWeek = (System.Web.UI.WebControls.FirstDayOfWeek) configFirstDay;
			Calendar1.SelectedDate = _entryHolder.EntryDate;
			Calendar1.VisibleDate = _entryHolder.EntryDate;
		}

		private void Calendar1_Change(object sender, System.EventArgs e)
		{
			HiddenDate.Text = Calendar1.SelectedDate.ToShortDateString();
			_entryHolder.EntryDate = Calendar1.SelectedDate;

			// Calendar can be accessed from FormMain or FormDetail
			if (HiddenOrigin.Text.ToString() == FormName.FormMain.ToString())
				ActiveForm = FormMain;
			else
				ActiveForm = FormDetail;
		}

		//*********************************************************************
		//
		//	This method set the display for FormDetail based on user's entry.
		//
		//*********************************************************************

		private void PopulateFormDetail(TimeEntry entry)
		{
			ProjectLabel.Text = "Project: " + entry.ProjectName + "  ";
			EntryDescriptionText.Text = entry.Description;
			HoursText.Text = entry.Duration.ToString();
			HiddenLogID.Text = entry.EntryLogID.ToString();
			HiddenProjectID.Text = entry.ProjectID.ToString();
			HiddenProjectName.Text = entry.ProjectName;
			HiddenDate.Text = entry.EntryDate.ToShortDateString();
		}

		//*********************************************************************
		//
		// Populate Timesheet grid based on UserID and dates range.
		// When using device specific code, re-use this function to populate time entries.
		//
		//*********************************************************************

		private void BindTimeSheet(ObjectList olGrid, int userID, DateTime start, DateTime end)
		{
			TimeEntriesCollection entryList = TimeEntry.GetEntries(userID, userID, start, end);

			//Use Selected Index to zero as default to enable ViewMode Setting
			olGrid.SelectedIndex = 0;
			olGrid.ViewMode = ObjectListViewMode.List;

			if (entryList.Count > 0) 
			{
				entryList.Sort(TimeEntriesCollection.TimeEntryFields.Day, true);
				olGrid.DataSource = entryList;
				olGrid.DataBind();
			}
			else 
				olGrid.Items.Clear();
		}

		//*********************************************************************
		//
		// Populate Project list box based on UserID.
		// When using device specific code, re-use this function to populate project list box.
		//
		//*********************************************************************

		private ProjectsCollection BindProjectList(SelectionList cboProject, int userID) 
		{
			ProjectsCollection dsProject = Project.GetProjects(userID, userID);
			cboProject.DataSource = dsProject;
			cboProject.DataBind();
			
			return dsProject;
		}

		//*********************************************************************
		//
		// Populate Category list based on ProjectID and find the selected index of the categoryID parameter.
		// When using device specific code, re-use this function to populate category drop down list.
		//
		//*********************************************************************

		private void BindCategoryList(SelectionList cboCategory, int projectID, int categoryID)
		{
			CategoriesCollection dsCategory = Project.GetCategories(projectID);
			cboCategory.DataSource = dsCategory;
			cboCategory.DataBind();
			cboCategory.SelectedIndex = FindCategoryIndex(cboCategory, categoryID);
		}

		//*********************************************************************
		//
		// Bind Day Selection List and find the selected index for the selectedDay parameter
		// When using device specific code, re-use this function to populate Day drop down list
		// For inserting new time entry, selectedDay will be today's date
		// For updating, selectedDay is the same as selectedDate
		//
		//*********************************************************************

		private void BindDayList(SelectionList cboDay, DateTime selectedDate, DateTime selectedDay)
		{
			DataTable dtEntryWeek = TimeEntry.GetWeek(selectedDate);
			cboDay.DataSource = dtEntryWeek;
			cboDay.DataBind();
			cboDay.SelectedIndex = FindDayIndex(cboDay, selectedDay);
		}

		//*********************************************************************
		//
		// Find the Category list's selected index for the specific Category ID.
		//
		//*********************************************************************

		private int FindCategoryIndex(SelectionList cboCategory, int categoryID)
		{
			int index = 0;
			foreach (MobileListItem item in cboCategory.Items)
			{
				if (((Category) item.DataItem).CategoryID == categoryID) break;
				index++;
			}

			if (index == cboCategory.Items.Count)
				return -1;
			else
				return index;
		}

		//*********************************************************************
		//
		// Find the Project list's selected index for the specific Project ID.
		//
		//*********************************************************************

		private int FindProjectIndex(SelectionList cboProject, int projectID)
		{
			int index = 0;
			foreach (MobileListItem item in cboProject.Items)
			{
				if (((Project) item.DataItem).ProjectID == projectID) break;
				index++;
			}

			if (index == cboProject.Items.Count)
				return -1;
			else
				return index;
		}

		//*********************************************************************
		//
		// Find the Day list's selected index for the specific Date.
		//
		//*********************************************************************

		private int FindDayIndex(SelectionList cboDay, DateTime entryDate)
		{
			int index = 0;
			foreach (MobileListItem item in cboDay.Items)
			{
				DataRowView row = (DataRowView) item.DataItem;
				if (row["Day"].ToString().CompareTo(entryDate.ToString("ddd")) == 0) break;
				index++;
			}

			if (index == cboDay.Items.Count)
				return -1;
			else
				return index;
		}

		#region Web Form Designer generated code
		override protected void OnInit(EventArgs e)
		{
			//
			// CODEGEN: This call is required by the ASP.NET Web Form Designer.
			//
			InitializeComponent();
			base.OnInit(e);
		}

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{    
			this.ChangeWeekMain.Click += new System.EventHandler(this.ChangeWeekMain_Click);
			this.TimeEntryGrid.ItemSelect += new System.Web.UI.MobileControls.ObjectListSelectEventHandler(this.TimeEntryGrid_Select);
			this.TimeEntryGrid.ItemDataBind += new System.Web.UI.MobileControls.ObjectListDataBindEventHandler(this.TimeEntryGrid_ItemBind);
			this.TimeEntryGrid.ItemCommand += new System.Web.UI.MobileControls.ObjectListCommandEventHandler(this.TimeEntryGrid_ItemCommand);
			this.FormMain.Activate += new System.EventHandler(this.FormMain_Activate);
			this.SelectProjectCommand.Click += new System.EventHandler(this.SelectProjectCommand_Click);
			this.FormProject.Activate += new System.EventHandler(this.FormProject_Activate);
			this.ChangeWeekDetail.Click += new System.EventHandler(this.ChangeWeekDetail_Click);
			this.ChangeProjectCommand.Click += new System.EventHandler(this.ChangeProjectCommand_Click);
			this.CategoryList.SelectedIndexChanged += new System.EventHandler(this.CategoryList_SelectedIndexChanged);
			this.SaveCommand.Click += new System.EventHandler(this.SaveCommand_Click);
			this.DeleteCommand.Click += new System.EventHandler(this.DeleteCommand_Click);
			this.CancelCommand.Click += new System.EventHandler(this.CancelCommand_Click);
			this.FormDetail.Activate += new System.EventHandler(this.FormDetail_Activate);
			this.Calendar1.SelectionChanged += new System.EventHandler(this.Calendar1_Change);
			this.FormCalendar.Activate += new System.EventHandler(this.FormCalendar_Activate);
			this.Load += new System.EventHandler(this.Page_Load);

		}
		#endregion

		private void TimeEntryGrid_ItemCommand(object sender, System.Web.UI.MobileControls.ObjectListCommandEventArgs e) {
		
		}

		private void CategoryList_SelectedIndexChanged(object sender, System.EventArgs e) {
		
		}

		
	}
}
