Imports System.IO

Imports File = System.IO.File

Public Class myAppointment
    Private Sub myStaff_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        fillGrid(dgv_appointment, fileLoc_Appointment)
        ' fills the grid when the user loadths form

        ' StartPosition = FormStartPosition.CenterScreen
        ' centering of screen occurs in design code


        ' sets the colours for the textbox using the values from my design
        txt_appID.BackColor = gray
        txt_staffID.BackColor = gray
        txt_cusID.BackColor = gray
        txt_cusName.BackColor = gray
        txt_staffIDApp.BackColor = gray
        txt_staffNameApp.BackColor = gray
        DTP_Appointment.BackColor = gray
        DTP_booking.BackColor = gray
        txt_tOA.BackColor = gray
        txt_treatmentID.BackColor = gray
        txt_service1.BackColor = gray
        txt_service2.BackColor = gray
        txt_service3.BackColor = gray
        txt_serviceName1.BackColor = gray
        txt_serviceName2.BackColor = gray
        txt_serviceName3.BackColor = gray
    End Sub

    Private Sub fillText(ByVal rowIndex As Integer)
        txt_appID.Text = dgv_appointment.Rows(rowIndex).Cells(0).Value
        txt_staffID.Text = dgv_appointment.Rows(rowIndex).Cells(1).Value
        txt_cusID.Text = dgv_appointment.Rows(rowIndex).Cells(2).Value
        ' taking the value from current row

        txt_cusName.Text = Decryption(FindField(fileLoc_Customer, txt_cusID.Text, 1)) + " " + Decryption(FindField(fileLoc_Customer, txt_cusID.Text, 2))
        ' combines the forename and surname from the customer file for the customer ID

        txt_staffIDApp.Text = dgv_appointment.Rows(rowIndex).Cells(3).Value
        ' taking the value from current row

        txt_staffNameApp.Text = Decryption(FindField(fileLoc_Staff, txt_staffIDApp.Text, 1)) + " " + Decryption(FindField(fileLoc_Staff, txt_staffIDApp.Text, 2))
        ' combines the forename and surname from the Staff file from the staff ID

        ' error handling for the MinValue if a date wasn't assigned, avoids crashes
        If Not dgv_appointment.Rows(rowIndex).Cells(4).Value = Date.MinValue Then
            DTP_booking.Value = dgv_appointment.Rows(rowIndex).Cells(4).Value
            DTP_Appointment.Value = dgv_appointment.Rows(rowIndex).Cells(5).Value
            ' taking the value from current row
        End If
        txt_tOA.Text = dgv_appointment.Rows(rowIndex).Cells(6).Value
        txt_treatmentID.Text = dgv_appointment.Rows(rowIndex).Cells(7).Value
        ' taking the value from current row


        txt_treatmentName.Text = FindField(fileLoc_Appointment, txt_treatmentID.Text, 2)
        ' finds the name of the treatment from the file by taking the ID and searching, avoids memorising the names of the treatments

        Dim ServiceUse As Integer = FindField(fileLoc_Appointment, txt_appID.Text, 8)
        ' Finds the service use from the appointment record, does it this way as it doesn't appear on the table
        txt_service1.Text = FindField(FileLoc_ServiceUse, ServiceUse, 2)
        txt_service2.Text = FindField(FileLoc_ServiceUse, ServiceUse, 3)
        txt_service3.Text = FindField(FileLoc_ServiceUse, ServiceUse, 4)
        ' Searches the service use file with the found ID to find the appropriate service IDs

        txt_serviceName1.Text = FindField(FileLoc_Service, txt_service1.Text, 2)
        txt_serviceName2.Text = FindField(FileLoc_Service, txt_service2.Text, 2)
        txt_serviceName3.Text = FindField(FileLoc_Service, txt_service3.Text, 2)
        ' Takes the name from the service file by using the ID found in the above code
    End Sub




    Private Sub clearText()
        txt_appID.Text = ""
        txt_staffID.Text = ""
        txt_cusID.Text = ""
        txt_cusName.Text = ""
        txt_staffIDApp.Text = ""
        txt_staffNameApp.Text = ""
        DTP_booking.Text = ""
        DTP_Appointment.Text = ""
        txt_tOA.Text = ""
        txt_treatmentID.Text = ""
        txt_service1.Text = ""
        txt_service2.Text = ""
        txt_service3.Text = ""
        txt_serviceName1.Text = ""
        txt_serviceName2.Text = ""
        txt_serviceName3.Text = ""
        ' Subroutine to clear all the text boxes on screen, can be called anywhere in the form
    End Sub



    'Navigation
    Private dgvNavigator As New DataGridViewNavigator()
    ' Allows the form to have access to the subroutines in the class
    Private Sub btn_first_Click(sender As Object, e As EventArgs) Handles btn_first.Click
        dgvNavigator.SelectFirst(dgv_appointment)
        fillText(dgvNavigator.CurrentIndex)     ' Fills boxes with information from currently viewed record
    End Sub

    Private Sub btn_previous_Click(sender As Object, e As EventArgs) Handles btn_previous.Click
        dgvNavigator.SelectPrevious(dgv_appointment)
        fillText(dgvNavigator.CurrentIndex)     ' Fills boxes with information from currently viewed record
    End Sub

    Private Sub btn_next_Click(sender As Object, e As EventArgs) Handles btn_next.Click
        dgvNavigator.SelectNext(dgv_appointment)
        fillText(dgvNavigator.CurrentIndex)     ' Fills boxes with information from currently viewed record
    End Sub

    Private Sub btn_last_Click(sender As Object, e As EventArgs) Handles btn_last.Click
        dgvNavigator.SelectLast(dgv_appointment)
        fillText(dgvNavigator.CurrentIndex)     ' Fills boxes with information from currently viewed record
    End Sub
    '----------------------------------------------------------------------------------------------'
    Private Sub btn_add_Click(sender As Object, e As EventArgs) Handles btn_add.Click
        clearText()
        Dim newID As Integer = AddRecord(fileLoc_Appointment)
        txt_appID.Text = newID
        txt_staffID.Text = userID
    End Sub

    Private Sub btn_save_Click(sender As Object, e As EventArgs) Handles btn_save.Click
        ' Compiles the data to create a string that is passed onto the SaveRecord subroutine in the module

        If Check() = False Then
            ' Runs check
            Return
        End If


        Dim appointmentID As String = txt_appID.Text

        ' Services are optional additions to appointments, below creates the ServiceUse which is the way the program keeps referential integrity
        Dim service1ID As String = txt_service1.Text
        Dim service2ID As String = txt_service2.Text
        Dim service3ID As String = txt_service3.Text

        Dim serviceUserID As Integer = ServiceUseCreate(appointmentID, service1ID, service2ID, service3ID)



        If UniqueCheck(appointmentID, fileLoc_Appointment) Then
            ' If the appointmentID is unique to the file, it will go ahead with adding the new appointment

            Dim newAppointment As String = txt_appID.Text & "," & txt_staffID.Text & "," & txt_cusID.Text & "," & txt_staffIDApp.Text & "," & DTP_booking.Value.Date & "," & DTP_Appointment.Value.Date & "," & txt_tOA.Text & "," & txt_treatmentID.Text & "," & serviceUserID
            ' Compiles the data into a String
            MsgBox(newAppointment)
            ' Displays the new record to the user in a MsgBox
            SaveRecord(fileLoc_Appointment, newAppointment)
            ' Passes on new Record to SaveRecord subroutine in the module
            fillGrid(dgv_appointment, fileLoc_Appointment)
            ' Refreshes dataGrid to show new record
        Else
            MsgBox("ID is not unique.")
        End If

    End Sub

    Private Function ServiceUseCreate(ByVal AppointmentID As String, Optional Service1 As String = "-1", Optional Service2 As String = "-1", Optional Service3 As String = "-1")
        Dim newID As String = AddRecord(FileLoc_ServiceUse)
        '-1 representing a null answer.

        Dim serviceValid As Boolean = True

        serviceValid = ServiceCheck(serviceValid, Service1, Service2, Service3)
        If serviceValid = True Then
            ' Service valid checks to see if a non null input was made into a service ID. if an attempt of adding a service was made, and it doesn't exist, it wont create the ServiceUse
            Dim newServiceUse As String = newID & "," & AppointmentID & "," & Service1 & "," & Service2 & "," & Service3
            SaveRecord(FileLoc_ServiceUse, newServiceUse)
            Return newID
        End If
        Return True
    End Function

    Private Function ServiceCheck(ByRef ServiceValid As Boolean, Optional Service1 As String = "-1", Optional Service2 As String = "-1", Optional Service3 As String = "-1")

        ' Checks the validity of any Services

        If Not (Service1 = "-1" Or Service1 = "") Then
            If BinSearch(Service1, FileLoc_Service, 0) = False Then
                serviceValid = False

            End If
        End If


        If Not (Service2 = "-1" Or Service2 = "") Then
            If BinSearch(Service2, FileLoc_Service, 0) = False Then
                serviceValid = False
            End If
        End If

        If Not (Service3 = "-1" Or Service3 = "") Then
            If BinSearch(Service3, FileLoc_Service, 0) = False Then
                serviceValid = False
            End If
        End If

        Return ServiceValid

    End Function

    Private Function Check()

        ' Check is a function that changes on the form and checks each field in the forms given record 
        ' If it can make it to the end of the function without returning a false, it is treated as valid data 
        If txt_appID.Text = "" Then
            ' Runs a presence check on the Appointment ID
            MsgBox("please enter an appointment ID")
            Return False
        End If

        If Not IntCheck(txt_appID.Text) Then
            ' Int checks the appointment ID
            Return False
        End If

        Dim staffId As Integer = txt_staffID.Text
        If BinSearch(staffId, fileLoc_Staff, 0) = False Then
            ' Checks that the staff ID exists in the text file
            MsgBox("invalid Staff ID")
            Return False
        End If

        Dim staffIdApp As Integer = txt_staffIDApp.Text
        If BinSearch(staffIdApp, fileLoc_Staff, 0) = False Then
            ' Validates the existence of the staff ID appointed
            MsgBox("invalid Appointed Staff ID")
            Return False
        End If

        ' Below looks to see if there exists a timetable on the date that the appointment is scheduled to be on

        Dim index As Integer = 0
        ' An integer that will be incremented to go through the timetable ID's

        Dim timetableTrue As Boolean = False
        ' Initially set as false, iterative algorithm below will have to prove that there does exist a Timetable to flip this


        For Each line As String In fileLoc_timetable





            Dim indString As String = CStr(index)
            Dim timetableDate As Date = FindFieldButDate(fileLoc_timetable, indString, 1)
            ' Uses the FindFieldButDate function to return the date of the given timetable 
            If timetableDate = DTP_Appointment.Value.Date Then
                ' Compares the timetableDate to the date of the appointment, if they match, the boolean value is set to true
                timetableTrue = True
                Exit For
            Else

                index = index + 1
                ' Increments by 1
            End If


        Next

        If timetableTrue = False Then
            Return False
        End If






        Dim shift1 As Integer = FindField(fileLoc_timetable, index, 2)
        Dim shift2 As Integer = FindField(fileLoc_timetable, index, 3)
        Dim shift3 As Integer = FindField(fileLoc_timetable, index, 4)
        Dim shift4 As Integer = FindField(fileLoc_timetable, index, 5)
        Dim shift5 As Integer = FindField(fileLoc_timetable, index, 6)


        Dim StaffShift As Integer = 0

        ' When it is established that there is a timetable on the date, the code below checks each of 5 shifts on the timetable to see if the staff is assigned to one of them
        ' If the staff member is, the integer staff shift will hold the shift ID that contains the start and finish time of the shift
        If txt_staffIDApp.Text = FindField(fileLoc_Shift, shift1, 2) Then
            StaffShift = shift1
        End If

        If txt_staffIDApp.Text = FindField(fileLoc_Shift, shift2, 2) Then
            StaffShift = shift2
        End If

        If txt_staffIDApp.Text = FindField(fileLoc_Shift, shift3, 2) Then
            StaffShift = shift3
        End If

        If txt_staffIDApp.Text = FindField(fileLoc_Shift, shift4, 2) Then
            StaffShift = shift4
        End If

        If txt_staffIDApp.Text = FindField(fileLoc_Shift, shift5, 2) Then
            StaffShift = shift5
        End If

        If StaffShift = 0 Then
            ' this will happen if the staff ID is not associated with any of the shifts
            Return False
        End If

        'if this point is reached, there is a timetable that is on the day of the appointment, and the staff id appointed is on a shift during that time,
        'below is checking that the time of the appointment is within the bounds of the shift

        Dim part() As String = txt_tOA.Text.Split(":")
        IntCheck(part(0))
        IntCheck(part(1))
        Dim hour As Integer = CInt(part(0))
        Dim minute As Integer = CInt(part(1))
        If hour < 0 Or hour > 24 Then
            ' Format Checking of the time
            MsgBox("invalid Hour")
            Return False
        End If

        If minute < 0 Or minute > 60 Then
            ' Format Checking of the time
            MsgBox("invalid minute")
            Return False
        End If


        Dim shiftStart As String = FindField(fileLoc_Shift, StaffShift, 3)
        Dim shiftEnd As String = FindField(fileLoc_Shift, StaffShift, 4)


        Dim partStart() As String = shiftStart.Split(":")
        ' Splits the time into two spots in an array, 0 being the hour and 1 being the minutes
        Dim partEnd() As String = shiftEnd.Split(":")


        If Not (part(0) > partStart(0) AndAlso part(0) < partEnd(0)) Then
            ' Not logic applied on top of a check if the time is within the bounds of the shift 
            MsgBox("Time of appointment is outside the shift bounds")
            Return False
        End If

        If part(0) < partStart(0) OrElse (part(0) = partStart(0) AndAlso part(1) < partStart(1)) Then
            ' Checks to see if the appointment hour is before the start of the shift, or if it the same hour, but the minute is before the shift
            Return False
        End If


        Dim CusId As Integer = txt_cusID.Text
        If BinSearch(CusId, fileLoc_Customer, 0) = False Then
            ' Validates the existence of the customer id
            MsgBox("invalid Customer ID")
            Return False
        End If

        Dim treatmentID As Integer = txt_treatmentID.Text
        If BinSearch(treatmentID, fileLoc_treatment, 0) = False Then
            MsgBox("invalid Treatment ID")
            Return False
        End If

        Dim booking As String = DTP_booking.Value.Date
        Dim Appointment As String = DTP_Appointment.Value.Date

        Dim BookingParts As String() = booking.Split("/")
        Dim AppointmentParts As String() = Appointment.Split("/")
        'part 0 is day, 1 is month, 2 is year

        If CInt(BookingParts(2)) > CInt(AppointmentParts(2)) Then
            MsgBox("Year of booking is later than year of appointment")
            Return False
        End If

        If CInt(BookingParts(2)) < CInt(AppointmentParts(2)) Then
            ' If the year of the appointment is after the year of the booking, the month and day are irrelevant, hence making checking them unnecessary
            GoTo postdate
        End If

        If CInt(BookingParts(1)) > CInt(AppointmentParts(1)) Then
            MsgBox("Month of booking is later than month of appointment")
            Return False
        End If

        If CInt(BookingParts(1)) < CInt(AppointmentParts(1)) Then
            ' If the month of the appointment is after the month of booking, then checking the day is irrelevant
            GoTo postdate
        End If

        If CInt(BookingParts(0)) > CInt(AppointmentParts(0)) Then
            MsgBox("Day of booking is later than day of appointment")
            Return False
        End If

        If txt_tOA.Text.Length > 5 Then
            MsgBox("Invalid time of appointment")
            Return False
        End If
postdate:   ' Is reached if the year is greater or the month is greater
        ' The Idea is that if the year or month is greater, the date is irrelevent.



        Return True




    End Function




    Private Sub btn_edit_Click(sender As Object, e As EventArgs) Handles btn_edit.Click

        If Check() = False Then
            ' Checks the new information
            Return
        End If



        Dim ID As Integer = txt_appID.Text
        Dim ServiceUse As Integer = FindField(fileLoc_Appointment, txt_appID.Text, 8)
        Dim newValues As String = txt_appID.Text & "," & txt_staffID.Text & "," & txt_cusID.Text & "," & txt_staffIDApp.Text & "," & DTP_booking.Value.Date & "," & DTP_Appointment.Value.Date & "," & txt_tOA.Text & "," & txt_treatmentID.Text & "," & ServiceUse
        ' Compiles the TextBox inputs as a string called newValues, that is passed onto the EditRecord along with the primary key ID that is used to find the record that is being edited
        EditRecord(ID, newValues, fileLoc_Appointment)
        fillGrid(dgv_appointment, fileLoc_Appointment)
        ' Grid is refreshed to show new changed


        Dim service1 As String = txt_service1.Text
        Dim service2 As String = txt_service2.Text
        Dim service3 As String = txt_service3.Text

        Dim IDString As String = CStr(ID)
        ' Converts the ID of the appoint to a string to be treated as a string in the editing of a record
        Dim serviceValid As Boolean = True
        serviceValid = ServiceCheck(serviceValid, service1, service2, service3)
        ' Checks the validity of any services added to the appointment

        If serviceValid = True Then
            ' Edits the ServiceUse to reflect and additions and removals of services to the file
            Dim newServiceUse As String = ServiceUse & "," & IDString & "," & service1 & "," & service2 & "," & service3
            EditRecord(ServiceUse, newServiceUse, FileLoc_ServiceUse)
        End If

    End Sub
    Private Sub btn_delete_Click(sender As Object, e As EventArgs) Handles btn_delete.Click
        If txt_appID.Text = "" Then
            ' Avoids a crash if a blank ID is input
            Return
        End If
        Dim appID As Integer = txt_appID.Text
        ' Gives an integer value for the record that the user is trying to delete

        DeleteRecord(dgv_appointment, fileLoc_Appointment, appID)

        fillGrid(dgv_appointment, fileLoc_Appointment)
        ' Refreshes grid
    End Sub

    Private Sub btn_menu_Click(sender As Object, e As EventArgs) Handles btn_menu.Click
        ' Takes user back to main menu
        Me.Visible = False
        myMenu.Visible = True
    End Sub

    '' Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    ''  Dim Customername As String = InputBox("please enter the customer name to search for appointments under that name")
    'gets the name that is being searched

    ''  Dim customerIDs As List(Of String) = LikeSearch(Customername, fileLoc_Customer, 1)
    'Searches for the name, if it matches (LIKE Logic) then it will store it in the string

    ''Dim AppointmentIDs As List(Of String) = LikeSearch2(customerIDs, fileLoc_Appointment, 2)
    ''   Console.WriteLine(AppointmentIDs)
    ''   Console.WriteLine(customerIDs)
    ''  ShowOnGrid(AppointmentIDs, dgv_appointment)


    '' End Sub


    ''Public Function LikeSearch(Field As Object, fileloc As String, part As Int16)


    ''   Dim sr As New StreamReader(fileloc)
    'sets up a variable to read the wanted file
    '' Dim lines As String() = File.ReadAllLines(fileloc)
    'stores all the lines in the file
    '' Dim searchedIDs As New List(Of String)
    'creates a new list the stores all the IDs

    ''For Each line As String In lines
    '' Dim parts As String() = line.Split(","c)
    'splits each record by the commas
    ''If Field Like parts(part) Then
    ''          searchedIDs.Add(parts(0))
    'adds the ID to the list
    ' '      End If


    '  '   Next

    ''    sr.Close()

    ''    Return searchedIDs

    '' End Function


    '
    '' Public Sub ShowOnGrid(Ids As Object, dgv As DataGridView)

    ' ' For Each row As DataGridViewRow In dgv.Rows
    ''If Not row.IsNewRow Then

    ''Dim ID As String = row.Cells(0).Value.ToString()
    'splits each record by the commas
    ''If Ids.contains(ID) Then
    ''            row.Visible = True
    'adds the ID to the list
    ''Else
    ' '               row.Visible = False

    ' 'End If

    ''End If
    ' 'Next

    ''End Sub



    Private Sub Button6_Click(sender As Object, e As EventArgs)
        'Brings up the help tab
        myHelp.Visible = True
    End Sub

    Private Sub txt_cusID_TextChanged(sender As Object, e As EventArgs) Handles txt_cusID.TextChanged
        ' When an ID is put in the appointed customer, the name is automatically placed
        txt_cusName.Text = Decryption(FindField(fileLoc_Customer, txt_cusID.Text, 1)) + " " + Decryption(FindField(fileLoc_Customer, txt_cusID.Text, 2))
    End Sub

    Private Sub txt_staffIDApp_TextChanged(sender As Object, e As EventArgs) Handles txt_staffIDApp.TextChanged
        ' When an ID is put in the appointed staff, the name is automatically placed
        txt_staffNameApp.Text = Decryption(FindField(fileLoc_Staff, txt_staffIDApp.Text, 1)) + " " + Decryption(FindField(fileLoc_Staff, txt_staffIDApp.Text, 2))
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles btn_AppIDAsc.Click
        ' Sorts appointments by ID ascending
        AscSort(fileLoc_Appointment, 0)
        fillGrid(dgv_appointment, fileLoc_Appointment)
    End Sub

    Private Sub btn_appIDDesc_Click(sender As Object, e As EventArgs) Handles btn_appIDDesc.Click
        ' Sorts appointments by ID Descending
        DescSort(fileLoc_Appointment, 0)
        fillGrid(dgv_appointment, fileLoc_Appointment)
    End Sub
End Class