module UnitySignalsModule
    use UnitySignalVariables
    use SimulationVariables
    use RedisInterface
contains

subroutine UnitySignalsFromJson(jsonfile)
    type(json_value),pointer :: parent
    type(json_core) :: json
    type(json_value),pointer :: p,pval
    type(json_file)::jsonfile
    logical::found
    integer :: i

    call jsonfile%get('UnitySignals.MudBucket',data%State%unitySignals%MudBucket,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%MudBucket")
    call jsonfile%get('UnitySignals.Elevator',data%State%unitySignals%Elevator,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Elevator")
    call jsonfile%get('UnitySignals.FillupHead',data%State%unitySignals%FillupHead,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%FillupHead")
    call jsonfile%get('UnitySignals.Ibop',data%State%unitySignals%Ibop,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Ibop")
    call jsonfile%get('UnitySignals.Kelly',data%State%unitySignals%Kelly,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Kelly")
    call jsonfile%get('UnitySignals.MouseHole',data%State%unitySignals%MouseHole,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%MouseHole")
    call jsonfile%get('UnitySignals.OperationCondition',data%State%unitySignals%OperationCondition,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%OperationCondition")
    call jsonfile%get('UnitySignals.SafetyValve',data%State%unitySignals%SafetyValve,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%SafetyValve")
    call jsonfile%get('UnitySignals.operation',data%State%unitySignals%operation,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%operation")
    call jsonfile%get('UnitySignals.Slips',data%State%unitySignals%Slips,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Slips")
    call jsonfile%get('UnitySignals.Slips_S',data%State%unitySignals%Slips_S,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Slips_S")
    call jsonfile%get('UnitySignals.Swing',data%State%unitySignals%Swing,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Swing")
    call jsonfile%get('UnitySignals.Swing_S',data%State%unitySignals%Swing_S,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Swing_S")
    call jsonfile%get('UnitySignals.TdsBackupClamp',data%State%unitySignals%TdsBackupClamp,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsBackupClamp")
    call jsonfile%get('UnitySignals.TdsSpine',data%State%unitySignals%TdsSpine,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsSpine")
    call jsonfile%get('UnitySignals.TdsSwing',data%State%unitySignals%TdsSwing,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsSwing")
    call jsonfile%get('UnitySignals.TdsTong',data%State%unitySignals%TdsTong,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsTong")
    call jsonfile%get('UnitySignals.Tong',data%State%unitySignals%Tong,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Tong")
    call jsonfile%get('UnitySignals.Tong_S',data%State%unitySignals%Tong_S,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%Tong_S")
    call jsonfile%get('UnitySignals.TdsConnectionModes',data%State%unitySignals%TdsConnectionModes,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsConnectionModes")
    call jsonfile%get('UnitySignals.TdsElevatorModes',data%State%unitySignals%TdsElevatorModes,found)
    if ( .not. found ) call logg(4,"Not found: unitySignals%TdsElevatorModes")

end subroutine

subroutine Set_TdsElevatorModes(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
        if(data%State%unitySignals%TdsElevatorModes == v) return
    #endif
    data%State%unitySignals%TdsElevatorModes = v
    !**call TdsElevatorModesEnum%OnTdsElevatorModesChange%RunAll()
end subroutine

integer function Get_TdsElevatorModes()
    implicit none
    Get_TdsElevatorModes = data%State%unitySignals%TdsElevatorModes
end function

subroutine Set_Ibop_Install()
    implicit none
    call Set_Ibop(IBOP_INSTALL)
end subroutine

subroutine Set_Ibop_Remove()
    implicit none
    call Set_Ibop(IBOP_REMOVE)
end subroutine

subroutine Set_Tong(v)
    implicit none
    integer , intent(in) :: v
    if(data%State%unitySignals%Tong == v) return
    data%State%unitySignals%Tong = v
    if(print_log) print*, 'Tong=', data%State%unitySignals%Tong
    if(data%State%unitySignals%Tong==TONG_MAKEUP_BEGIN) call publishMessageToChannel("TONG_MAKEUP_BEGIN")
    if(data%State%unitySignals%Tong==TONG_BREAKOUT_BEGIN) call publishMessageToChannel("TONG_BREAKOUT_BEGIN")
    !**call data%State%unitySignals%OnTongChange%RunAll()
end subroutine

integer function Get_Tong()
    implicit none
    Get_Tong = data%State%unitySignals%Tong
end function


subroutine Set_TdsTong(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%TdsTong == v) return
    #endif
    data%State%unitySignals%TdsTong = v
    #ifdef deb
            if(print_log) print*, 'TdsTong=', data%State%unitySignals%TdsTong
    #endif
    !**call data%State%unitySignals%OnTdsTongChange%RunAll()
end subroutine

integer function Get_TdsTong()
    implicit none
    Get_TdsTong = data%State%unitySignals%TdsTong
end function


subroutine Set_TdsSwing(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%TdsSwing == v) return
    #endif
    data%State%unitySignals%TdsSwing = v
    #ifdef deb
            if(print_log) print*, 'TdsSwing=', data%State%unitySignals%TdsSwing
    #endif
    !**call data%State%unitySignals%OnTdsSwingChange%RunAll()
end subroutine

integer function Get_TdsSwing()
    implicit none
    Get_TdsSwing = data%State%unitySignals%TdsSwing
end function


subroutine Set_TdsSpine(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%TdsSpine == v) return
    #endif
    data%State%unitySignals%TdsSpine = v
    #ifdef deb
            if(print_log) print*, 'TdsSpine=', data%State%unitySignals%TdsSpine
    #endif
    !**call data%State%unitySignals%OnTdsSpineChange%RunAll()
end subroutine

integer function Get_TdsSpine()
    implicit none
    Get_TdsSpine = data%State%unitySignals%TdsSpine
end function


subroutine Set_TdsBackupClamp(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%TdsBackupClamp == v) return
    #endif
    data%State%unitySignals%TdsBackupClamp = v
    #ifdef deb
            if(print_log) print*, 'TdsBackupClamp=', data%State%unitySignals%TdsBackupClamp
    #endif
    !**call data%State%unitySignals%OnTdsBackupClampChange%RunAll()
end subroutine

integer function Get_TdsBackupClamp()
    implicit none
    Get_TdsBackupClamp = data%State%unitySignals%TdsBackupClamp
end function


subroutine Set_Swing(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%Swing == v) return
    #endif
    data%State%unitySignals%Swing = v
    #ifdef deb
            if(print_log) print*, 'Swing=', data%State%unitySignals%Swing
    #endif
    !**call data%State%unitySignals%OnSwingChange%RunAll()
end subroutine

integer function Get_Swing()
    implicit none
    Get_Swing = data%State%unitySignals%Swing
end function

!//TODO: apparently every thing is started here for slips
subroutine Set_Slips(v)
    implicit none
    integer , intent(in) :: v
    if(data%State%unitySignals%Slips == v) return
    data%State%unitySignals%Slips = v
    if(print_log) print*, 'Slips=', data%State%unitySignals%Slips
    if(v==SLIPS_SET_BEGIN) call publishMessageToChannel("SLIPS_SET_BEGIN")
    if(v==SLIPS_UNSET_BEGIN) call publishMessageToChannel("SLIPS_UNSET_BEGIN")
    !**call data%State%unitySignals%OnSlipsChange%RunAll()
end subroutine

integer function Get_Slips()
    implicit none
    Get_Slips = data%State%unitySignals%Slips
end function

subroutine Set_Operation(i)
    implicit none 
    integer, intent (in) :: i
    data%State%unitySignals%operation = i
end subroutine

subroutine Set_SafetyValve(v)
    implicit none
    integer , intent(in) :: v
#ifdef ExcludeExtraChanges
    if(data%State%unitySignals%SafetyValve == v) return
#endif        
    data%State%unitySignals%SafetyValve = v
#ifdef deb
    if(data%State%unitySignals%SafetyValve == SAFETY_VALVE_NEUTRAL) then
        if(print_log) print*, 'SafetyValve=SAFETY_VALVE_NEUTRAL' 
    else if (data%State%unitySignals%SafetyValve == SAFETY_VALVE_INSTALL) then
        if(print_log) print*, 'SafetyValve=SAFETY_VALVE_INSTALL'
    else if (data%State%unitySignals%SafetyValve == SAFETY_VALVE_INSTALL) then
        if(print_log) print*, 'SafetyValve=SAFETY_VALVE_REMOVE'
    endif
#endif
    !**call data%State%unitySignals%OnSafetyValveChange%RunAll()
end subroutine

integer function Get_SafetyValve()
    implicit none
    Get_SafetyValve = data%State%unitySignals%SafetyValve
end function

subroutine Set_SafetyValve_Install()
    implicit none
    call Set_SafetyValve(SAFETY_VALVE_INSTALL)
end subroutine

subroutine Set_SafetyValve_Remove()
    implicit none
    call Set_SafetyValve(SAFETY_VALVE_REMOVE)
end subroutine


subroutine Set_OperationCondition(v)
    ! use CKellyEnumVariables
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%OperationCondition == v) return
    #endif
    data%State%unitySignals%OperationCondition = v
    #ifdef deb
            if(print_log) print*, 'OperationCondition=', data%State%unitySignals%OperationCondition
    #endif
    !**call data%State%unitySignals%OnOperationConditionChange%RunAll()
    !**call data%State%unitySignals%OnOperationConditionChangeInt%RunAll(data%State%unitySignals%OperationCondition)
end subroutine

integer function Get_OperationCondition()
    implicit none
    Get_OperationCondition = data%State%unitySignals%OperationCondition
end function

subroutine Evaluate_OperationCondition()
    implicit none    
end subroutine


subroutine Set_MouseHole(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%MouseHole == v) return
    #endif
    !call sleep(2)
    data%State%unitySignals%MouseHole = v
    #ifdef deb
            if(print_log) print*, 'MouseHole=', data%State%unitySignals%MouseHole
    #endif
    !**call data%State%unitySignals%OnMouseHoleChange%RunAll()
end subroutine

integer function Get_MouseHole()
    implicit none
    Get_MouseHole = data%State%unitySignals%MouseHole
end function
    


subroutine Set_Kelly(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%Kelly == v) return
    #endif
    data%State%unitySignals%Kelly = v
    #ifdef deb
            if(print_log) print*, 'Kelly=', data%State%unitySignals%Kelly
    #endif
    !**call data%State%unitySignals%OnKellyChange%RunAll()
end subroutine

integer function Get_Kelly()
    implicit none
    Get_Kelly = data%State%unitySignals%Kelly
end function


subroutine Set_Ibop(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%Ibop == v) return
    #endif
    data%State%unitySignals%Ibop = v
    #ifdef deb
            if(print_log) print*, 'Ibop=', data%State%unitySignals%Ibop
    #endif
    !**call data%State%unitySignals%OnIbopChange%RunAll()
end subroutine

integer function Get_Ibop()
    implicit none
    Get_Ibop = data%State%unitySignals%Ibop
end function


subroutine Set_FillupHead(v)
    use CManifolds, only: ToggleFillupHead
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%FillupHead == v) return
    #endif
    data%State%unitySignals%FillupHead = v
    
    if (data%State%unitySignals%FillupHead == FILLUP_HEAD_INSTALL) then
        call ToggleFillupHead(.true.)
    else if (data%State%unitySignals%FillupHead == FILLUP_HEAD_REMOVE) then
        call ToggleFillupHead(.false.)
    endif
    
    #ifdef deb
            if(print_log) print*, 'FillupHead=', data%State%unitySignals%FillupHead
    #endif
    !**call data%State%unitySignals%OnFillupHeadChange%RunAll()
end subroutine

integer function Get_FillupHead()
    implicit none
    Get_FillupHead = data%State%unitySignals%FillupHead
end function

subroutine Evaluate_FillupHead()
    use CHoistingVariables
    use SimulationVariables
    use CStudentStationVariables!, only: data%State%StudentStation%FillupHeadInstallation
    implicit none
    
    if (data%Configuration%Hoisting%DriveType == TopDrive_DriveType) then
#ifdef OST
        if(print_log) print*, 'Evaluate_FillupHead=TopDrive'
#endif
    endif
    
    
    
    
    
    
    if (data%Configuration%Hoisting%DriveType == Kelly_DriveType) then
#ifdef OST
        if(print_log) print*, 'Evaluate_FillupHead=Kelly'
#endif
    endif
    
    
    if (Get_FillupHead() == FILLUP_HEAD_INSTALL) then
        data%State%StudentStation%FillupHeadInstallation = .true.
    else if (Get_FillupHead() == FILLUP_HEAD_REMOVE) then
        data%State%StudentStation%FillupHeadInstallation = .false.
    endif
    
end subroutine


subroutine Set_Elevator(v)
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%Elevator == v) return
    #endif
    data%State%unitySignals%Elevator = v
    #ifdef deb
            if(print_log) print*, 'Elevator=', data%State%unitySignals%Elevator
    #endif
    !**call data%State%unitySignals%OnElevatorChange%RunAll()
end subroutine

integer function Get_Elevator()
    implicit none
    Get_Elevator = data%State%unitySignals%Elevator
end function



subroutine Set_MudBucket(v)
    use CManifolds, only: ToggleMudBox
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%MudBucket == v) return
    #endif
    data%State%unitySignals%MudBucket = v
    if (data%State%unitySignals%MudBucket == MUD_BUCKET_INSTALL) then
        call ToggleMudBox(.true.)
    else if (data%State%unitySignals%MudBucket == MUD_BUCKET_REMOVE) then
        call ToggleMudBox(.false.)
    endif
    #ifdef deb
            if(print_log) print*, 'MudBucket=', data%State%unitySignals%MudBucket
    #endif
    !**call data%State%unitySignals%OnMudBucketChange%RunAll()
end subroutine

integer function Get_MudBucket()
    implicit none
    Get_MudBucket = data%State%unitySignals%MudBucket
end function

subroutine Evaluate_MudBucket()
    use CStudentStationVariables!, only: data%State%StudentStation%MudBoxInstallation
    implicit none        
    
    if (Get_MudBucket() == MUD_BUCKET_INSTALL) then
        data%State%StudentStation%MudBoxInstallation = .true.
    else if (Get_MudBucket() == MUD_BUCKET_REMOVE) then
        data%State%StudentStation%MudBoxInstallation = .false.
    endif
    
end subroutine


!! Moved from CTdsConnectionModeEnum

subroutine Set_TdsConnectionModes(v)
    use CManifolds, Only: KellyConnected, KellyDisconnected
    implicit none
    integer , intent(in) :: v
    #ifdef ExcludeExtraChanges
            if(data%State%unitySignals%TdsConnectionModes == v) return
    #endif
    data%State%unitySignals%TdsConnectionModes = v
    
    if(data%State%unitySignals%TdsConnectionModes == TDS_CONNECTION_NOTHING) then
        call KellyDisconnected()
    else
        call KellyConnected()
    endif
    
    #ifdef deb
            if(print_log) print*, 'data%State%unitySignals%TdsConnectionModes=', data%State%unitySignals%TdsConnectionModes
    #endif
    !**call data%State%unitySignals%OnTdsConnectionModesChange%RunAll()
end subroutine

integer function Get_TdsConnectionModes()
    use SimulationVariables
    implicit none
    Get_TdsConnectionModes = data%State%unitySignals%TdsConnectionModes
end function

subroutine Evaluate_TdsConnectionModes()
    use CUnityInputs
    use SimulationVariables
    use UnityModule
    implicit none
    
    if (data%Configuration%Hoisting%DriveType == TopDrive_DriveType) then
        #ifdef OST
                    if(print_log) print*, 'Evaluate_TdsConnectionModes=TopDrive'
        #endif
        !TOPDRIVE-CODE=3
        if (Get_TdsStemIn() .and.&
            Get_TdsSpine() == TDS_SPINE_CONNECT_END .and.&
            !TopDriveDrillTorqueState == TdsMu_SPINE
            Get_TdsConnectionModes() == TDS_CONNECTION_NOTHING) then
        
            call Set_TdsConnectionModes(TDS_CONNECTION_SPINE)
            return
        end if
                            
        !TOPDRIVE-CODE=4
        if (Get_TdsTong() == TDS_TONG_MAKEUP_END .and.&
            Get_TdsConnectionModes() == TDS_CONNECTION_SPINE ) then
        
            call Set_TdsConnectionModes(TDS_CONNECTION_STRING)
            data%Equipments%TopDrivePanel%TopDriveTorqueWrenchLed = LED_OFF
            return
        end if
            
        !TOPDRIVE-CODE=5
        if (Get_TdsTong() == TDS_TONG_BREAKOUT_END .and.&
            Get_TdsConnectionModes() == TDS_CONNECTION_STRING ) then
        
            call Set_TdsConnectionModes(TDS_CONNECTION_SPINE)
            data%Equipments%TopDrivePanel%TopDriveTorqueWrenchLed = LED_OFF
            return
        end if
            
        !TOPDRIVE-CODE=6
        if (Get_TdsSpine() == TDS_SPINE_DISCONNECT_END .and.&
            !Get_TdsStemIn() == .false. .and.&
            Get_TdsConnectionModes() == TDS_CONNECTION_SPINE) then
        
            call Set_TdsConnectionModes(TDS_CONNECTION_NOTHING)
            return
        end if

    endif
    
    if (data%Configuration%Hoisting%DriveType == Kelly_DriveType) then
        #ifdef OST
                    if(print_log) print*, 'Evaluate_TdsConnectionModes=Kelly'
        #endif
    endif
    
end subroutine

end module UnitySignalsModule