Option Strict Off
Imports System.Collections
Imports Microsoft.Win32
Imports System.Text.RegularExpressions
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Security
Imports System.ComponentModel
Imports Microsoft.Win32.SafeHandles
Imports System.Runtime.ConstrainedExecution
Imports System.Security.Permissions

Public Class Class1
    Implements GOverlayPlugin.Interfaces.IPlugin
    Public testvar As Integer = 1

    Private objHost As GOverlayPlugin.Interfaces.IHost
    Public PluginName As String = "Sensors Mix"
    Public LastCache As New System.Collections.Hashtable

    Public Sub Initialize(ByVal Host As GOverlayPlugin.Interfaces.IHost) Implements GOverlayPlugin.Interfaces.IPlugin.Initialize
        objHost = Host
    End Sub

    Public ReadOnly Property Description() As String Implements GOverlayPlugin.Interfaces.IPlugin.Description
        'Return your plugin name
        Get
            Return "This plugin allows to mix one or more sensors together." & vbNewLine & vbNewLine & _
                "Developed by TheLaGmAn"
        End Get
    End Property

    Public ReadOnly Property Name() As String Implements GOverlayPlugin.Interfaces.IPlugin.Name
        'Return your plugin name
        Get
            Return PluginName
        End Get
    End Property

    Public ReadOnly Property Display() As String Implements GOverlayPlugin.Interfaces.IPlugin.Display
        'Return the display this plugin belongs to
        Get
            Return "lcdsys"
        End Get
    End Property

    Public Function MixSensors(sensorId)
        Dim method = sensorId
        If method = "SM.SensorGroup1" Or method = "SM.SensorGroup2" Or method = "SM.SensorGroup3" Or method = "SM.SensorGroup4" Or method = "SM.SensorGroup5" Then
            'objHost.DebugMessage("a")
            Dim sId = 1
            If method = "SM.SensorGroup1" Then
                sId = "1"
            ElseIf method = "SM.SensorGroup2" Then
                sId = "2"
            ElseIf method = "SM.SensorGroup3" Then
                sId = "3"
            ElseIf method = "SM.SensorGroup4" Then
                sId = "4"
            ElseIf method = "SM.SensorGroup5" Then
                sId = "5"
            End If


            Dim s1data = 0
            Dim s2data = 0
            Dim s3data = 0
            Dim s4data = 0
            Dim ssum = 0
            Dim sdiv = 0
            Dim s1 = objHost.AccessHost("plugin_options", PluginName, "g" & sId & "s1", "")
            Dim s2 = objHost.AccessHost("plugin_options", PluginName, "g" & sId & "s2", "")
            Dim s3 = objHost.AccessHost("plugin_options", PluginName, "g" & sId & "s3", "")
            Dim s4 = objHost.AccessHost("plugin_options", PluginName, "g" & sId & "s4", "")
            'objHost.DebugMessage("s1: " & s1)
            'objHost.DebugMessage("s2: " & s2)
            'objHost.DebugMessage("s3: " & s3)
            If s1 <> "" Then
                'objHost.DebugMessage("a1")
                s1data = objHost.AccessHost("retrieve", "GLOBAL_CachedValues", s1, "")
                If s1data Is Nothing Then
                    objHost.DebugMessage("asked to replace marks")
                    objHost.AccessHost("replacemarks", s1, "", "")
                End If
                ssum = ssum + s1data
                sdiv = sdiv + 1
            End If
            If s2 <> "" Then
                'objHost.DebugMessage("a2")
                s2data = objHost.AccessHost("retrieve", "GLOBAL_CachedValues", s2, "")
                If s2data Is Nothing Then
                    objHost.DebugMessage("asked to replace marks")
                    objHost.AccessHost("replacemarks", s2, "", "")
                End If
                ssum = ssum + s2data
                sdiv = sdiv + 1
            End If
            If s3 <> "" Then
                'objHost.DebugMessage("a3")
                s3data = objHost.AccessHost("retrieve", "GLOBAL_CachedValues", s3, "")
                If s3data Is Nothing Then
                    objHost.DebugMessage("asked to replace marks")
                    objHost.AccessHost("replacemarks", s3, "", "")
                End If
                ssum = ssum + s3data
                sdiv = sdiv + 1
            End If
            If s4 <> "" Then
                'objHost.DebugMessage("a3")
                s4data = objHost.AccessHost("retrieve", "GLOBAL_CachedValues", s4, "")
                If s4data Is Nothing Then
                    objHost.DebugMessage("asked to replace marks")
                    objHost.AccessHost("replacemarks", s4, "", "")
                End If
                ssum = ssum + s4data
                sdiv = sdiv + 1
            End If

            Return (ssum) / sdiv

        End If
    End Function
    Function CallBack(method As String) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CallBacks
        'Callbacks from GOverlay
        Dim returnHT As Hashtable = New Hashtable
        Try
            If method = "willrequestvalues" Then
                'This is done to perform a refresh of all the sensors but we dont need it, sensors refresh on request
            Else
                'When GOverlay request a sensor here, it wants the value (if any) to use it with the GOverlat default sensor display (not your own drawing method)
                Dim value As Integer = 0
                value = MixSensors(method)
                returnHT("value") = value
                Return returnHT
            End If
        Catch ex As Exception
            objHost.DebugMessage("Plugin error: " & ex.Message & ": " & ex.StackTrace)
            Return returnHT
        End Try
    End Function

    Function AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.AvailableSensors
        'Create the list of the sensors/elements this plugin has
        'You can access your pluginOptions here as pluginOptions(your_option)        
        Dim sensors As New System.Collections.Generic.Dictionary(Of String, String)
        Try
            sensors.Add("SM.SensorGroup1", pluginOptions("g1n"))
            sensors.Add("SM.SensorGroup2", pluginOptions("g2n"))
            sensors.Add("SM.SensorGroup3", pluginOptions("g3n"))
            sensors.Add("SM.SensorGroup4", pluginOptions("g4n"))
            sensors.Add("SM.SensorGroup5", pluginOptions("g5n"))
            Return sensors
        Catch ex As Exception
            objHost.DebugMessage("Error loading sensors:" & ex.Message & ": " & ex.StackTrace)
            Return sensors
        End Try
    End Function

    Function LCDSys2_AvailableSensors(pluginOptions As Hashtable) As System.Collections.Generic.Dictionary(Of String, String) Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_AvailableSensors
        Return AvailableSensors(pluginOptions)
    End Function

    Function SensorHasCustomDraw(sensor_name As String) As Boolean Implements GOverlayPlugin.Interfaces.IPlugin.SensorHasCustomDraw
        'All sensors are drawn with GOverlay default drawing
        Return False
    End Function


    Function ComboBoxes() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.ComboBoxes
        'Create custom ComboBox for your configuration to use
        Return New Hashtable
    End Function

    Public Function SetDefaultOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.SetDefaultOptions
        'Set the default values you want to have on your sensor when its created, if the user doesnt change any option, he will have this settings
        Return elementData
    End Function

    Public Function CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorBasic: Combo with basic colors for the regular text font
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'TextSize: Combo with options (Extra Small=4, Very Small=5, Small=10, Normal=15, Big=20, Very Big=30, Extreme=40)
        'FontStyle2: Combo with options (Regular Font=0, Square Font=1, Numbers Font 1=2
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Here you can also load your custom comboboxes

        'No options because GOverlay draws instead of us
        Return New Hashtable
    End Function

    Public Function LCDSys2_CreateOptions(sensorId As String, elementData As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_CreateOptions
        'Set the options the user will have when clicking on the element
        'The available option_types are:
        'Text: Input text
        'Combo3: Combo with options (Enabled=0, Disabled=1)
        'Sensors: Combo with available sensors
        'ColorRGB: Combo with common RGB colors = 16bitinteger
        'ComboOnOff: Combo with options (Disabled=0, Enabled=1)
        'ComboYesNo: Combo with options (Yes=Yes, No=No)
        'FontStyle: Combo with options of the fonts the user has installed
        'Orientation: Combo with options (Horizontal=0, Vertical=1)
        'Alignment: Left=-1,Center=0,Right=1
        'Here you can also load your custom comboboxes

        'No options because GOverlay draws instead of us
        Return New Hashtable
    End Function


    Public Function PluginOptionsDefault() As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptionsDefault
        'Set the default values you want to have on plugin, if the user doesnt change any option, he will have this settings
        Dim options As New Hashtable

        'options("test") = ""

        options("g1n") = "Sensor Group 1"
        options("g2n") = "Sensor Group 2"
        options("g3n") = "Sensor Group 3"
        options("g4n") = "Sensor Group 4"
        options("g5n") = "Sensor Group 5"

        options("g1s1") = ""
        options("g1s2") = ""
        options("g1s3") = ""
        options("g1s4") = ""

        options("g2s1") = ""
        options("g2s2") = ""
        options("g2s3") = ""
        options("g2s4") = ""

        options("g3s1") = ""
        options("g3s2") = ""
        options("g3s3") = ""
        options("g3s4") = ""

        options("g4s1") = ""
        options("g4s2") = ""
        options("g4s3") = ""
        options("g4s4") = ""

        options("g5s1") = ""
        options("g5s2") = ""
        options("g5s3") = ""
        options("g5s4") = ""

        Return options
    End Function
    Public Function PluginOptions(pluginCurrentOptions As Hashtable) As Hashtable Implements GOverlayPlugin.Interfaces.IPlugin.PluginOptions
        'Set the options the user will have when going to the plugins tab and clicking on your plugin
        'The availalbe option_type are teh same as CreateOptions function
        Dim options As New Hashtable
        'Option: option_index as integer, option_data as ArrayList
        'Option_Data: option_type as string, option_label as string, option_name as string (no spaces, no _)
        Dim pos As Integer = 20 : pos = pos - 1
        options.Add(pos, New ArrayList({"Text", "Group 1 - Name", "g1n"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 1 - Sensor #1", "g1s1"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 1 - Sensor #2", "g1s2"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 1 - Sensor #3", "g1s3"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 1 - Sensor #4", "g1s4"})) : pos = pos - 1

        options.Add(pos, New ArrayList({"Text", "Group 2 - Name", "g2n"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 2 - Sensor #1", "g2s1"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 2 - Sensor #2", "g2s2"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 2 - Sensor #3", "g2s3"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 2 - Sensor #4", "g2s4"})) : pos = pos - 1

        options.Add(pos, New ArrayList({"Text", "Group 3 - Name", "g3n"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 3 - Sensor #1", "g3s1"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 3 - Sensor #2", "g3s2"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 3 - Sensor #3", "g3s3"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 3 - Sensor #4", "g3s4"})) : pos = pos - 1

        options.Add(pos, New ArrayList({"Text", "Group 4 - Name", "g4n"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 4 - Sensor #1", "g4s1"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 4 - Sensor #2", "g4s2"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 4 - Sensor #3", "g4s3"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 4 - Sensor #4", "g4s4"})) : pos = pos - 1

        options.Add(pos, New ArrayList({"Text", "Group 5 - Name", "g5n"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 5 - Sensor #1", "g5s1"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 5 - Sensor #2", "g5s2"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 5 - Sensor #3", "g5s3"})) : pos = pos - 1
        options.Add(pos, New ArrayList({"Sensors", "Group 5 - Sensor #4", "g5s4"}))

        Return options
    End Function

    Public Function DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.DisplayOnLCD
        'GOverlay draws instead of us
        Return New ArrayList
    End Function


    Public Function LCDSys2_DisplayOnLCD(sensorId As String, elementData As Hashtable, pluginOptions As Hashtable, cacheRuns As Integer) As ArrayList Implements GOverlayPlugin.Interfaces.IPlugin.LCDSys2_DisplayOnLCD
        'GOverlay draws instead of us
        Return New ArrayList
    End Function


    Public Function convertcolorto16bit(cr As Integer, cg As Integer, cb As Integer) As Integer

        Dim R As Double
        Dim G As Double
        Dim B As Double

        R = cr / 256 * 32
        G = cg / 256 * 64
        B = cb / 256 * 32

        R = Math.Floor(R)
        G = Math.Floor(G)
        B = Math.Floor(B)

        Dim final As Int32 = (CInt(R) << 11)
        final = final + Int(G << 5)
        final = final + Int(B)

        Return final

    End Function



#Region "Native API Signatures and Types"

    ''' <summary>
    ''' Access rights for file mapping objects
    ''' http://msdn.microsoft.com/en-us/library/aa366559.aspx
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum FileMapAccess
        FILE_MAP_COPY = 1
        FILE_MAP_WRITE = 2
        FILE_MAP_READ = 4
        FILE_MAP_ALL_ACCESS = &HF001F
    End Enum


    ''' <summary>
    ''' Represents a wrapper class for a file mapping handle. 
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity(), _
    HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort:=True)> _
    Friend NotInheritable Class SafeFileMappingHandle
        Inherits SafeHandleZeroOrMinusOneIsInvalid

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Private Sub New()
            MyBase.New(True)
        End Sub

        <SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode:=True)> _
        Public Sub New(ByVal handle As IntPtr, ByVal ownsHandle As Boolean)
            MyBase.New(ownsHandle)
            MyBase.SetHandle(handle)
        End Sub

        <ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), _
        DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function CloseHandle(ByVal handle As IntPtr) _
        As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

        Protected Overrides Function ReleaseHandle() As Boolean
            Return SafeFileMappingHandle.CloseHandle(MyBase.handle)
        End Function

    End Class


    Friend ReadOnly INVALID_HANDLE_VALUE As New IntPtr(-1)


    ''' <summary>
    ''' The class exposes Windows APIs used in this code sample.
    ''' </summary>
    ''' <remarks></remarks>
    <SuppressUnmanagedCodeSecurity()> _
    Friend Class NativeMethod

        ''' <summary>
        ''' Opens a named file mapping object.
        ''' </summary>
        ''' <param name="dwDesiredAccess">
        ''' The access to the file mapping object. This access is checked against 
        ''' any security descriptor on the target file mapping object.
        ''' </param>
        ''' <param name="bInheritHandle">
        ''' If this parameter is TRUE, a process created by the CreateProcess 
        ''' function can inherit the handle; otherwise, the handle cannot be 
        ''' inherited.
        ''' </param>
        ''' <param name="lpName">
        ''' The name of the file mapping object to be opened.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is an open handle to the 
        ''' specified file mapping object.
        ''' </returns>
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function OpenFileMapping( _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal bInheritHandle As Boolean, _
            ByVal lpName As String) _
            As SafeFileMappingHandle
        End Function


        ''' <summary>
        ''' Maps a view of a file mapping into the address space of a calling 
        ''' process.
        ''' </summary>
        ''' <param name="hFileMappingObject">
        ''' A handle to a file mapping object. The CreateFileMapping and 
        ''' OpenFileMapping functions return this handle.
        ''' </param>
        ''' <param name="dwDesiredAccess">
        ''' The type of access to a file mapping object, which determines the 
        ''' protection of the pages.
        ''' </param>
        ''' <param name="dwFileOffsetHigh">
        ''' A high-order DWORD of the file offset where the view begins.
        ''' </param>
        ''' <param name="dwFileOffsetLow">
        ''' A low-order DWORD of the file offset where the view is to begin.
        ''' </param>
        ''' <param name="dwNumberOfBytesToMap">
        ''' The number of bytes of a file mapping to map to the view. All bytes 
        ''' must be within the maximum size specified by CreateFileMapping.
        ''' </param>
        ''' <returns>
        ''' If the function succeeds, the return value is the starting address of
        ''' the mapped view.
        ''' </returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function MapViewOfFile( _
            ByVal hFileMappingObject As SafeFileMappingHandle, _
            ByVal dwDesiredAccess As FileMapAccess, _
            ByVal dwFileOffsetHigh As UInt32, _
            ByVal dwFileOffsetLow As UInt32, _
            ByVal dwNumberOfBytesToMap As UInt32) _
            As IntPtr
        End Function


        ''' <summary>
        ''' Unmaps a mapped view of a file from the calling process's address 
        ''' space.
        ''' </summary>
        ''' <param name="lpBaseAddress">
        ''' A pointer to the base address of the mapped view of a file that is to 
        ''' be unmapped.
        ''' </param>
        ''' <returns></returns>
        <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Public Shared Function UnmapViewOfFile( _
            ByVal lpBaseAddress As IntPtr) _
            As <MarshalAs(UnmanagedType.Bool)> Boolean
        End Function

    End Class

#End Region
End Class