# Copyright 2026 PostalPortal LLC
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that
# the following conditions are met:
#   1. Redistributions of source code must retain
#      the above copyright notice, this list of conditions
#      and the following disclaimer.
#   2. Redistributions in binary form must reproduce
#      the above copyright notice, this list of conditions
#      and the following disclaimer in the documentation
#      and/or other materials provided with the distribution.
#   3. Neither the name of the copyright holder
#       nor the names of its contributors may be used
#       to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
# WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.


currentScanModeIndex = 1
gotScanModeList = True
scanModeList = [""]
inhibitScan = False

newUsbListReport = None

def queueNewListReportForProcessing(report_data):
    global newUsbListReport
    newUsbListReport = bytes(report_data)

# Parse report 0x55 if there's one queued for processing
def processNewListUSBReport():
    global newUsbListReport
    if newUsbListReport is None:
        return
    report = newUsbListReport
    newUsbListReport = None
    if len(report) < 2:
        # Not valid at all
        return
    
    listlen = report[1]
    if listlen > len(report) - 2:
        # Length is claiming to be longer than the actual data is
        return
    
    payload = report[2 : 2 + listlen]
    newScanModeList = []
    for part in payload.split(b'\x00'):
        if part:
            try:
                newScanModeList.append(part.decode('ascii'))
            except:
                # Handle error on non-ASCII byte (value > 127)
                continue
    if len(newScanModeList) > 0:
        setScanModeIndex(1)
        setModeList(newScanModeList)
        setModeListIsSet(True)
    else:
        setScanModeIndex(0)
        setModeList([""])
        setModeListIsSet(False)


def setInhibitScan(b):
    global inhibitScan
    inhibitScan = b
    
def isScanInhibited():
    global inhibitScan
    return inhibitScan

def getCurrentModeStr():
    global gotScanModeList, scanModeList, currentScanModeIndex
    if gotScanModeList:
        return scanModeList[currentScanModeIndex - 1]
    else:
        return scanModeList[0]
    
def getPrevModeStr():
    global gotScanModeList, scanModeList, currentScanModeIndex
    if gotScanModeList and currentScanModeIndex > 1:
        return scanModeList[currentScanModeIndex - 2]
    else:
        return ""

def getNextModeStr():
    global gotScanModeList, scanModeList, currentScanModeIndex
    if gotScanModeList and len(scanModeList) > currentScanModeIndex:
        return scanModeList[currentScanModeIndex]
    else:
        return ""

def getCurrentModeID():
    global gotScanModeList, currentScanModeIndex
    if gotScanModeList:
        return currentScanModeIndex
    else:
        return 0
    
def setModeID(indx):
    global gotScanModeList, scanModeList, currentScanModeIndex
    if gotScanModeList:
        if indx > len(scanModeList):
            currentScanModeIndex = 1
        elif indx < 1:
            currentScanModeIndex = len(scanModeList)
        else:
            currentScanModeIndex = indx
    else:
        currentScanModeIndex = 0

def setScanModeIndex(idx):
    global currentScanModeIndex
    currentScanModeIndex = idx

def setModeListIsSet(b):
    global gotScanModeList
    gotScanModeList = b

def getModes():
    global scanModeList
    return scanModeList

def setModeList(modelist):
    global scanModeList
    scanModeList = modelist

def modeListIsSet():
    global gotScanModeList
    return gotScanModeList
