Imports System.Web.UI.MobileControls
Imports ASPNET.StarterKit.TimeTracker.BusinessLogicLayer

Namespace ASPNET.StarterKit.TimeTracker.Mobile

    '*********************************************************************
    '
    '	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
        Inherits System.Web.UI.MobileControls.MobilePage

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

        Private _entryHolder As New TimeEntry() ' User's input holder
        Private _user As TTUser
        Private _weekEndingDate As DateTime = DateTime.MinValue
        Private _weekStartingDate As DateTime = DateTime.MinValue
        Protected WithEvents DeleteCommand As System.Web.UI.MobileControls.Command
        Private _totalHours As Decimal = Decimal.Zero

        Private Enum FormName
            FormMain
            FormDetail
        End Enum 'FormName

        Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
            _user = New TTUser(TTSecurity.GetUserID(), User.Identity.Name, TTSecurity.GetName(), TTSecurity.GetUserRole())

            If Not IsPostBack Then
                _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 Not (CategoryList.Selection Is Nothing) Then
                    _entryHolder.CategoryID = Convert.ToInt32(CategoryList.Selection.Value)
                End If
                _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
                End Try
            End If
        End Sub 'Page_Load

        '*********************************************************************
        '
        '	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 Sub FormMain_Activate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FormMain.Activate
            TimeEntry.FillCorrectStartEndDates(_entryHolder.EntryDate, _weekStartingDate, _weekEndingDate)
            TotalHoursLabel.Text = "總時數: 0"
            WeekEndingMain.Text = "截至本週: " + _weekEndingDate.ToShortDateString() + "  "
            BindTimeSheet(TimeEntryGrid, _user.UserID, _weekStartingDate, _weekEndingDate)
        End Sub 'FormMain_Activate

        '*********************************************************************
        '
        '	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 Sub TimeEntryGrid_Select(ByVal sender As Object, ByVal e As System.Web.UI.MobileControls.ObjectListSelectEventArgs) Handles TimeEntryGrid.ItemSelect
            ' Load a new TimeEntry object based on selected EntryLogID
            Dim currentEntryLogID As Integer = Convert.ToInt32(e.ListItem("EntryLogID"))
            _entryHolder = New TimeEntry(currentEntryLogID)
            _entryHolder.Load()

            ActiveForm = FormDetail
        End Sub 'TimeEntryGrid_Select

        '*********************************************************************
        '
        '	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 Sub TimeEntryGrid_ItemBind(ByVal sender As Object, ByVal e As System.Web.UI.MobileControls.ObjectListDataBindEventArgs) Handles TimeEntryGrid.ItemDataBind
            ' Calculate total hours for this week and display
            _totalHours += CType(e.DataItem, TimeEntry).Duration
            TotalHoursLabel.Text = "總時數: " + _totalHours.ToString()
        End Sub 'TimeEntryGrid_ItemBind

        Private Sub ChangeWeekMain_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChangeWeekMain.Click
            ' Preserve the originated form before opening the calendar
            HiddenOrigin.Text = FormName.FormMain.ToString()
            ActiveForm = FormCalendar
        End Sub 'ChangeWeekMain_Click

        Protected Sub AddEntryCommand2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddEntryCommand2.Click
            ActiveForm = FormProject
        End Sub 'AddEntryCommand2_Click

		'*********************************************************************
		'
        '	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 Sub FormProject_Activate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FormProject.Activate
            Dim dsProject As ProjectsCollection = 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 And dsProject.Count > 0 Then
                _entryHolder.ProjectID = CType(dsProject(0), Project).ProjectID
            End If ' Otherwise, keep _entryHolder.ProjectID the same
            'Everytime ProjectList is bound, then find the correct index for it
            If Not (dsProject Is Nothing) Then
                ProjectListBox.SelectedIndex = FindProjectIndex(ProjectListBox, _entryHolder.ProjectID)
            End If
        End Sub 'FormProject_Activate

        Private Sub SelectProjectCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SelectProjectCommand.Click
            ' When FormProject is activated, there is ALWAYS a default selection 
            If ProjectListBox.Selection Is Nothing Then
                ' 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
            End If
        End Sub 'SelectProjectCommand_Click

        '*********************************************************************
        '
        '	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 Sub FormDetail_Activate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FormDetail.Activate
            TimeEntry.FillCorrectStartEndDates(_entryHolder.EntryDate, _weekStartingDate, _weekEndingDate)
            BindCategoryList(CategoryList, _entryHolder.ProjectID, _entryHolder.CategoryID)

            If _entryHolder.EntryLogID = 0 Then
                ' 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
            End If

            WeekEndingDetail.Text = "截至本週: " + _weekEndingDate.ToShortDateString() + "  "
            PopulateFormDetail(_entryHolder)
        End Sub 'FormDetail_Activate

        Private Sub ChangeWeekDetail_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChangeWeekDetail.Click
            ' Remember the originated form before opening the calendar
            HiddenOrigin.Text = FormName.FormDetail.ToString()
            ActiveForm = FormCalendar
        End Sub 'ChangeWeekDetail_Click

        Private Sub ChangeProjectCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChangeProjectCommand.Click
            ActiveForm = FormProject
        End Sub 'ChangeProjectCommand_Click

        Private Sub SaveCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveCommand.Click
            RequiredFieldValidatorHrs.Validate()
            RequiredFieldValidatorDesc.Validate()
            CompareValidatorHrs.Validate()

            If RequiredFieldValidatorHrs.IsValid And RequiredFieldValidatorDesc.IsValid And CompareValidatorHrs.IsValid Then
                ' 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)

                Dim time As 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
            End If
        End Sub 'SaveCommand_Click

        Private Sub DeleteCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DeleteCommand.Click
            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
        End Sub 'DeleteCommand_Click

        Private Sub CancelCommand_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelCommand.Click
            ' Reset _entryHolder for Session
            _entryHolder = New TimeEntry()
            _entryHolder.EntryDate = Convert.ToDateTime(DayList.Selection.Value)

            ' Reset Form Detail
            PopulateFormDetail(_entryHolder)
            ActiveForm = FormMain
        End Sub 'CancelCommand_Click

        '*********************************************************************
        '
        '	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 Sub FormCalendar_Activate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FormCalendar.Activate

            Dim configFirstDay As Integer = Convert.ToInt32(ConfigurationSettings.AppSettings(Global.CfgKeyFirstDayOfWeek))
            Calendar1.FirstDayOfWeek = CType(configFirstDay, System.Web.UI.WebControls.FirstDayOfWeek)
            Calendar1.SelectedDate = _entryHolder.EntryDate
            Calendar1.VisibleDate = _entryHolder.EntryDate
        End Sub 'FormCalendar_Activate

        Private Sub Calendar1_Change(ByVal sender As Object, ByVal e As System.EventArgs) Handles Calendar1.SelectionChanged
            HiddenDate.Text = Calendar1.SelectedDate.ToShortDateString()
            _entryHolder.EntryDate = Calendar1.SelectedDate

            ' Calendar can be accessed from FormMain or FormDetail
            If HiddenOrigin.Text.ToString() = FormName.FormMain.ToString() Then
                ActiveForm = FormMain
            Else
                ActiveForm = FormDetail
            End If
        End Sub 'Calendar1_Change

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

        Private Sub PopulateFormDetail(ByVal entry As TimeEntry)
            ProjectLabel.Text = "專案: " + 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()
        End Sub 'PopulateFormDetail

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

        Private Sub BindTimeSheet(ByVal olGrid As ObjectList, ByVal userID As Integer, ByVal start As DateTime, ByVal [end] As DateTime)
            Dim entryList As TimeEntriesCollection = 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 Then
                entryList.Sort(TimeEntriesCollection.TimeEntryFields.Day, True)
                olGrid.DataSource = entryList
                olGrid.DataBind()
            Else
                olGrid.Items.Clear()
            End If
        End Sub 'BindTimeSheet

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

        Private Function BindProjectList(ByVal cboProject As SelectionList, ByVal userID As Integer) As ProjectsCollection
            Dim dsProject As ProjectsCollection = Project.GetProjects(userID, userID)
            cboProject.DataSource = dsProject
            cboProject.DataBind()

            Return dsProject
        End Function 'BindProjectList

        '*********************************************************************
        '
        ' 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 Sub BindCategoryList(ByVal cboCategory As SelectionList, ByVal projectID As Integer, ByVal categoryID As Integer)
            Dim dsCategory As CategoriesCollection = Project.GetCategories(projectID)
            cboCategory.DataSource = dsCategory
            cboCategory.DataBind()
            cboCategory.SelectedIndex = FindCategoryIndex(cboCategory, categoryID)
        End Sub 'BindCategoryList

        '*********************************************************************
        '
        ' 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 Sub BindDayList(ByVal cboDay As SelectionList, ByVal selectedDate As DateTime, ByVal selectedDay As DateTime)
            Dim dtEntryWeek As DataTable = TimeEntry.GetWeek(selectedDate)
            cboDay.DataSource = dtEntryWeek
            cboDay.DataBind()
            cboDay.SelectedIndex = FindDayIndex(cboDay, selectedDay)
        End Sub 'BindDayList

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

        Private Function FindCategoryIndex(ByVal cboCategory As SelectionList, ByVal categoryID As Integer) As Integer
            Dim index As Integer = 0
            Dim item As MobileListItem
            For Each item In cboCategory.Items
                If CType(item.DataItem, Category).CategoryID = categoryID Then
                    Exit For
                End If
                index += 1
            Next item

            If index = cboCategory.Items.Count Then
                Return -1
            Else
                Return index
            End If
        End Function 'FindCategoryIndex

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

        Private Function FindProjectIndex(ByVal cboProject As SelectionList, ByVal projectID As Integer) As Integer
            Dim index As Integer = 0
            Dim item As MobileListItem
            For Each item In cboProject.Items
                If CType(item.DataItem, Project).ProjectID = projectID Then
                    Exit For
                End If
                index += 1
            Next item

            If index = cboProject.Items.Count Then
                Return -1
            Else
                Return index
            End If
        End Function 'FindProjectIndex

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

        Private Function FindDayIndex(ByVal cboDay As SelectionList, ByVal entryDate As DateTime) As Integer
            Dim index As Integer = 0
            Dim item As MobileListItem
            For Each item In cboDay.Items
                Dim row As DataRowView = CType(item.DataItem, DataRowView)
                If row("Day").ToString().CompareTo(entryDate.ToString("ddd")) = 0 Then
                    Exit For
                End If
                index += 1
            Next item

            If index = cboDay.Items.Count Then
                Return -1
            Else
                Return index
            End If
        End Function 'FindDayIndex 

#Region " Web Form Designer Generated Code "

        'This call is required by the Web Form Designer.
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

        End Sub

        Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
            'CODEGEN: This method call is required by the Web Form Designer
            'Do not modify it using the code editor.
            InitializeComponent()
        End Sub

#End Region

    End Class
End Namespace
