#!/bin/bash
#
# This script is to generate a complete configuration file needed for the myplace plugin
# This script can handle up to 3 independent AdvantageAir (AA) systems
#
# This script can be invoked in two ways:
# 1. from homebridge customUI
# 2. from a terminal
#
# Note: The version does not write any temporary files and use jq to create all config
#       It is a bit slow if you are using jq-1.6 because jq-1.6 is notorously slow!  
#       It is highly recommended to upgrade to jq-1.7.1
#
UIversion="customUI"

AAIP="${1}"
AAname="${2}"
extraTimers1="${3}"
AAdebug="${4}"
AAIP2="${5}"
AAname2="${6}"
extraTimers2="${7}"
AAdebug2="${8}"
AAIP3="${9}"
AAname3="${10}"
extraTimers3="${11}"
AAdebug3="${12}"
MYPLACE_SH_PATH="${13}"

# define the possible names for myPlace platform, HOOBS installation was known to have a different platform name.
myPlacePlatform=""
myPlacePlatform1="MyPlace"
myPlacePlatform2="homebridge-myplace"

# Initialize some JSON varialbles
myPlaceConstantsAA="{}"
myPlaceQueueTypesAA="{}"
myPlaceAccessoriesAA="{}"

# Set some BOOLEAN variables
hasAircons=false
hasLights=false
hasThings=false

# delclare an ID array
declare -a idArray

# fun color stuff
BOLD=$(tput bold)
TRED=$(tput setaf 1)
TGRN=$(tput setaf 2)
TYEL=$(tput setaf 3)
TPUR=$(tput setaf 5)
TLBL=$(tput setaf 6)
TNRM=$(tput sgr0)

function myPlaceBasicKeys()
{
   myPlaceBasicKeys="{}"
   myPlaceBasicKeys=$( echo "${myPlaceBasicKeys}" | jq ".title |= \"MyPlace configuration generated by Configuration Creator\"" \
                                                  | jq ".debug |= ${debugMyPlace}" \
                                                  | jq ".outputConstants |= false" \
                                                  | jq ".statusMsg |= true" \
                                                  | jq ".timeout |= 60000" \
                                                  | jq ".stateChangeResponseTime |= 0" )
}

function myPlaceConstants()
{
   local debugA=""

   if [ "${debug}" = "true" ]; then
      debugA="-debug"
   fi

   myPlaceConstants="{}"
   myPlaceConstants=$( echo "${myPlaceConstants}" | jq ".key |= \"${ip}\"" \
                                                  | jq ".value |= \"${IPA}${debugA}\"" )
 
   myPlaceConstantsAA=$( echo "${myPlaceConstantsAA}" | jq ".constants += [${myPlaceConstants}]" )
}

function myPlaceQueueTypes()
{
   myPlaceQueueTypes="{}"
   myPlaceQueueTypes=$( echo "${myPlaceQueueTypes}" | jq ".queue |= \"${queue}\"" \
                                                    | jq ".queueType |= \"WoRm2\"" )

   myPlaceQueueTypesAA=$( echo "${myPlaceQueueTypesAA}" | jq ".queueTypes += [${myPlaceQueueTypes}]" )
}

function myPlaceModelQueue()
{
   myPlaceModelQueue="{}"
   myPlaceModelQueue=$( echo "${myPlaceModelQueue}" | jq ".manufacturer |= \"Advantage Air Australia\"" \
                                                    | jq ".model |= \"${sysType}\"" \
                                                    | jq ".serialNumber |= \"${tspModel}\"" \
                                                    | jq ".queue |= \"${queue}\"" )
}

function myPlaceThermostat()
{
   local name="$1"
   local zone="$2"
   local ac_l=" ${ac}"

   if [ "${zone}" != "" ]; then zone="${zone} "; fi
   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceThermostat="{}"
   myPlaceThermostat=$( echo "${myPlaceThermostat}" | jq ".type |= \"Thermostat\"" \
                                                    | jq ".displayName |= \"${name}\"" \
                                                    | jq ".currentHeatingCoolingState |= \"OFF\"" \
                                                    | jq ".targetHeatingCoolingState |= \"OFF\"" \
                                                    | jq ".currentTemperature |= 24" \
                                                    | jq ".targetTemperature |= 24" \
                                                    | jq ".temperatureDisplayUnits |= \"CELSIUS\"" \
                                                    | jq ".name |= \"${name}\"" \
                                                    | jq ". += ${myPlaceModelQueue}" \
                                                    | jq ".polling[0].characteristic |= \"currentHeatingCoolingState\"" \
                                                    | jq ".polling[1].characteristic |= \"targetHeatingCoolingState\"" \
                                                    | jq ".polling[2].characteristic |= \"currentTemperature\"" \
                                                    | jq ".polling[3].characteristic |= \"targetTemperature\"" \
                                                    | jq ".props.targetTemperature.maxValue |= 32" \
                                                    | jq ".props.targetTemperature.minValue |= 16" \
                                                    | jq ".props.targetTemperature.minStep |= 1" \
                                                    | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                    | jq ".state_cmd_suffix |= \"${zone}${ip}${ac_l}\"" )

   if [[ "${zone}" = "" || "${zone}" = "noOtherThermostat " ]]; then
      myPlaceLinkedTypesFanSpeed "${name} FanSpeed" "${myPlaceThermostat}"
   fi
}

function myPlaceLinkedTypesFanSpeed()
{
   local name="$1"
   local motherAcc="$2"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceLinkedTypesFanSpeed="{}"
   myPlaceLinkedTypesFanSpeed=$( echo "${myPlaceLinkedTypesFanSpeed}" | jq ".type |= \"Fan\"" \
                                                                      | jq ".displayName |= \"${name}\"" \
                                                                      | jq ".on |= true" \
                                                                      | jq ".rotationSpeed |= 25" \
                                                                      | jq ".name |= \"${name}\"" \
                                                                      | jq ". += ${myPlaceModelQueue}" \
                                                                      | jq ".polling[0].characteristic |= \"on\"" \
                                                                      | jq ".polling[1].characteristic |= \"rotationSpeed\"" \
                                                                      | jq ".props.rotationSpeed.minStep |= 1" \
                                                                      | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                      | jq ".state_cmd_suffix |= \"fanSpeed ${ip}${ac_l}\"" )

   motherAcc=$( echo "${motherAcc}" | jq ".linkedTypes |= [${myPlaceLinkedTypesFanSpeed}]" )
   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${motherAcc}]" )
}

function myPlaceFanSwitch()
{
   local name="$1"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi
   myPlaceFanSwitch="{}"
   myPlaceFanSwitch=$( echo "${myPlaceFanSwitch}" | jq ".type |= \"Switch\"" \
                                                  | jq ".displayName |= \"${name}\"" \
                                                  | jq ".on |= false" \
                                                  | jq ".name |= \"${name}\"" \
                                                  | jq ". += ${myPlaceModelQueue}" \
                                                  | jq ".polling[0].characteristic |= \"on\"" \
                                                  | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                  | jq ".state_cmd_suffix |= \"${ip}${ac_l}\"" )

   myPlaceLinkedTypesFanSpeed "${nameA} FanSpeed" "${myPlaceFanSwitch}"
}

function myPlaceTimerLightbulb()
{
   local name="$1"
   local suffix="$2"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceTimerLightbulb="{}"
   myPlaceTimerLightbulb=$( echo "${myPlaceTimerLightbulb}" | jq ".type |= \"Lightbulb\"" \
                                                            | jq ".displayName |= \"${name}\"" \
                                                            | jq ".on |= false" \
                                                            | jq ".brightness |= 0" \
                                                            | jq ".name |= \"${name}\"" \
                                                            | jq ". += ${myPlaceModelQueue}" \
                                                            | jq ".polling[0].characteristic |= \"on\"" \
                                                            | jq ".polling[1].characteristic |= \"brightness\"" \
                                                            | jq ".props.brightness.minStep |= 1" \
                                                            | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                            | jq ".state_cmd_suffix |= \"${suffix} ${ip}${ac_l}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceTimerLightbulb}]" )
}

function myPlaceZoneFan()
{
   local name="$1"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceZoneFan="{}"
   myPlaceZoneFan=$( echo "${myPlaceZoneFan}" | jq ".type |= \"Fan\"" \
                                              | jq ".displayName |= \"${name}\"" \
                                              | jq ".on |= false" \
                                              | jq ".rotationSpeed |= 100" \
                                              | jq ".name |= \"${name}\"" \
                                              | jq ". += ${myPlaceModelQueue}" \
                                              | jq ".polling[0].characteristic |= \"on\"" \
                                              | jq ".polling[1].characteristic |= \"rotationSpeed\"" \
                                              | jq ".props.rotationSpeed.minStep |= 5" \
                                              | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                              | jq ".state_cmd_suffix |= \"${zoneStr} ${ip}${ac_l}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceZoneFan}]" )
}

function myPlaceZoneFanv2()
{
   local name="$1"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceZoneFanv2="{}"
   myPlaceZoneFanv2=$( echo "${myPlaceZoneFanv2}" | jq ".type |= \"Fanv2\"" \
                                                  | jq ".displayName |= \"${name}\"" \
                                                  | jq ".active |= 0" \
                                                  | jq ".rotationSpeed |= 100" \
                                                  | jq ".rotationDirection |= 1" \
                                                  | jq ".name |= \"${name}\"" \
                                                  | jq ". += ${myPlaceModelQueue}" \
                                                  | jq ".polling[0].characteristic |= \"active\"" \
                                                  | jq ".polling[1].characteristic |= \"rotationSpeed\"" \
                                                  | jq ".polling[2].characteristic |= \"rotationDirection\"" \
                                                  | jq ".props.rotationSpeed.minStep |= 5" \
                                                  | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                  | jq ".state_cmd_suffix |= \"${zoneStr} ${ip}${ac_l}\"" ) 

   # Append the Zone Thermostat as linkedTypes
   myPlaceZoneThermostat "${nameZ} Thermostat" "${zoneStr}"
   myPlaceZoneFanv2=$( echo "${myPlaceZoneFanv2}" | jq ".linkedTypes += [${myPlaceZoneThermostat}]" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceZoneFanv2}]" )
}

function myPlaceZoneThermostat()
{
   local name="$1"
   local zone="$2"
   local ac_l=" ${ac}"

   if [ "${zone}" != "" ]; then zone="${zone} "; fi
   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceZoneThermostat="{}"
   myPlaceZoneThermostat=$( echo "${myPlaceZoneThermostat}" | jq ".type |= \"Thermostat\"" \
                                                            | jq ".displayName |= \"${name}\"" \
                                                            | jq ".currentHeatingCoolingState |= \"OFF\"" \
                                                            | jq ".targetHeatingCoolingState |= \"OFF\"" \
                                                            | jq ".currentTemperature |= 24" \
                                                            | jq ".targetTemperature |= 24" \
                                                            | jq ".temperatureDisplayUnits |= \"CELSIUS\"" \
                                                            | jq ".name |= \"${name}\"" \
                                                            | jq ". += ${myPlaceModelQueue}" \
                                                            | jq ".polling[0].characteristic |= \"targetHeatingCoolingState\"" \
                                                            | jq ".polling[1].characteristic |= \"currentTemperature\"" \
                                                            | jq ".polling[2].characteristic |= \"targetTemperature\"" \
                                                            | jq ".props.targetTemperature.maxValue |= 32" \
                                                            | jq ".props.targetTemperature.minValue |= 16" \
                                                            | jq ".props.targetTemperature.minStep |= 1" \
                                                            | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                            | jq ".state_cmd_suffix |= \"${zone}${ip}${ac_l}\"" )
}

function myPlaceZoneFanv2noRotationDirection()
{
   local name="$1"
   local ac_l=" ${ac}"

   if [ "${ac_l}" = " ac1" ]; then ac_l=""; fi

   myPlaceZoneFanv2noRotationDirection="{}"
   myPlaceZoneFanv2noRotationDirection=$( echo "${myPlaceZoneFanv2noRotationDirection}" | jq ".type |= \"Fanv2\"" \
                                                                                        | jq ".displayName |= \"${name}\"" \
                                                                                        | jq ".active |= 0" \
                                                                                        | jq ".rotationSpeed |= 100" \
                                                                                        | jq ".name |= \"${name}\"" \
                                                                                        | jq ". += ${myPlaceModelQueue}" \
                                                                                        | jq ".polling[0].characteristic |= \"active\"" \
                                                                                        | jq ".polling[1].characteristic |= \"rotationSpeed\"" \
                                                                                        | jq ".props.rotationSpeed.minStep |= 5" \
                                                                                        | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                                        | jq ".state_cmd_suffix |= \"${zoneStr} ${ip}${ac_l}\"" )

   # Append the Zone Thermostat as linkedTypes
   myPlaceThermostat "${nameZ} Thermostat" "${zoneStr}"
   myPlaceZoneFanv2noRotationDirection=$( echo "${myPlaceZoneFanv2noRotationDirection}" | jq ".linkedTypes += [${myPlaceThermostat}]" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceZoneFanv2noRotationDirection}]" )
}

function myPlaceLightbulbNoDimmer()
{
   local name="$1"
   local id="$2"
   id=${id//\"/}
   myPlaceLightbulbNoDimmer="{}"
   myPlaceLightbulbNoDimmer=$( echo "${myPlaceLightbulbNoDimmer}" | jq ".type |= \"Lightbulb\"" \
                                                                  | jq ".displayName |= \"${name}\"" \
                                                                  | jq ".on |= false" \
                                                                  | jq ".name |= \"${name}\"" \
                                                                  | jq ". += ${myPlaceModelQueue}" \
                                                                  | jq ".polling[0].characteristic |= \"on\"" \
                                                                  | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                  | jq ".state_cmd_suffix |= \"ligID:$id ${ip}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceLightbulbNoDimmer}]" )
}

function myPlaceLightbulbWithDimmer()
{
   local name="$1"
   local id="$2"
   id=${id//\"/}
   myPlaceLightbulbWithDimmer="{}"
   myPlaceLightbulbWithDimmer=$( echo "${myPlaceLightbulbWithDimmer}" | jq ".type |= \"Lightbulb\"" \
                                                                      | jq ".displayName |= \"${name}\"" \
                                                                      | jq ".on |= false" \
                                                                      | jq ".brightness |= 80" \
                                                                      | jq ".name |= \"${name}\"" \
                                                                      | jq ". += ${myPlaceModelQueue}" \
                                                                      | jq ".polling[0].characteristic |= \"on\"" \
                                                                      | jq ".polling[1].characteristic |= \"brightness\"" \
                                                                      | jq ".props.brightness.minStep |= 1" \
                                                                      | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                      | jq ".state_cmd_suffix |= \"ligID:$id ${ip}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceLightbulbWithDimmer}]" )
}

function myPlaceFanNoRotationSpeed()
{
   local name="$1"
   local id="$2"
   id=${id//\"/}
   myPlaceFanNoRotationSpeed="{}"
   myPlaceFanNoRotationSpeed=$( echo "${myPlaceFanNoRotationSpeed}" | jq ".type |= \"Fan\"" \
                                                                    | jq ".displayName |= \"${name}\"" \
                                                                    | jq ".on |= false" \
                                                                    | jq ".name |= \"${name}\"" \
                                                                    | jq ". += ${myPlaceModelQueue}" \
                                                                    | jq ".polling[0].characteristic |= \"on\"" \
                                                                    | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                    | jq ".state_cmd_suffix |= \"ligID:$id ${ip}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceFanNoRotationSpeed}]" )
} 

function myPlaceGarageDoorOpener()
{
   local name="$1"
   local id="$2"
   id=${id//\"/}
   myPlaceGarageDoorOpener="{}"
   myPlaceGarageDoorOpener=$( echo "${myPlaceGarageDoorOpener}" | jq ".type |= \"GarageDoorOpener\"" \
                                                                | jq ".displayName |= \"${name}\"" \
                                                                | jq ".obstructionDetected |= false" \
                                                                | jq ".currentDoorState |= 1" \
                                                                | jq ".targetDoorState |= 1" \
                                                                | jq ".name |= \"${name}\"" \
                                                                | jq ". += ${myPlaceModelQueue}" \
                                                                | jq ".polling[0].characteristic |= \"currentDoorState\"" \
                                                                | jq ".polling[1].characteristic |= \"targetDoorState\"" \
                                                                | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                                | jq ".state_cmd_suffix |= \"thiID:$id ${ip}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceGarageDoorOpener}]" )
}

function myPlaceWindowCovering()
{
   local name="$1"
   local id="$2"
   id=${id//\"/}
   myPlaceWindowCovering="{}"
   myPlaceWindowCovering=$( echo "${myPlaceWindowCovering}" | jq ".type |= \"WindowCovering\"" \
                                                            | jq ".displayName |= \"${name}\"" \
                                                            | jq ".obstructionDetected |= false" \
                                                            | jq ".currentPosition |= 0" \
                                                            | jq ".positionState |= 2" \
                                                            | jq ".targetPosition |= 0" \
                                                            | jq ".name |= \"${name}\"" \
                                                            | jq ". += ${myPlaceModelQueue}" \
                                                            | jq ".polling[0].characteristic |= \"currentPosition\"" \
                                                            | jq ".polling[1].characteristic |= \"targetPosition\"" \
                                                            | jq ".state_cmd |= \"'${MYPLACE_SH_PATH}'\"" \
                                                            | jq ".state_cmd_suffix |= \"thiID:$id ${ip}\"" )

   myPlaceAccessoriesAA=$( echo "${myPlaceAccessoriesAA}" | jq ".accessories += [${myPlaceWindowCovering}]" )
}

function readHomebridgeConfigJson()
{
   case  $UIversion in
      customUI )
         DIR=$(pwd)
         homebridgeConfigJson="${DIR}/config.json"
         if [ -f "${homebridgeConfigJson}" ]; then
            # expand the json just in case it is in compact form
            config=$( jq '.' "${homebridgeConfigJson}" )
            checkForPlatformMyPlaceInHomebridgeConfigJson
            if [ -z "${validFile}" ]; then
               echo "ERROR: no MyPlace Config found in \"${homebridgeConfigJson}\"! Please ensure that Homebridge-MyPlace plugin is installed"
               exit 1
            fi
         else
            echo "ERROR: no Homebridge config.json found in \"${DIR}\"! You may copy the created \"$HOME/myPlaceConfigAA.json\" to MyPlace JASON Config manually."
            echo "${myPlaceConfigAA}" | sudo tee "$HOME/myPlaceConfigAA.json" > /dev/null
            exit 1
         fi
      ;;
      nonUI )
         INPUT=""
         homebridgeConfigJson=""
         getHomebridgeConfigJsonPath
         if [ "${fullPath}" != "" ]; then homebridgeConfigJson="${fullPath}"; fi

         # if no config.json file found, ask user to input the full path
         if [ -z "${homebridgeConfigJson}" ]; then
            homebridgeConfigJson=""
            echo ""
            echo "${TPUR}WARNING: No Homebridge config.json file located by the script!${TNRM}"
            echo ""
            until [ -n "${INPUT}" ]; do
               echo "${TYEL}Please enter the full path of your Homebridge config.json file,"
               echo "otherwise just hit enter to abort copying \"${myPlaceConfigAA}\" to Homebridge config.json."
               echo "The config.json path should be in the form of /*/*/*/config.json ${TNRM}"
               read -r -p "${BOLD}> ${TNRM}" INPUT
               if [ -z "${INPUT}" ]; then
                  echo "${TPUR}WARNING: No Homebridge config.json file specified"
                  echo "         Copying of ${myPlaceConfigAA} to Homebridge config.json was aborted"
                  echo ""
                  echo "${TLBL}${BOLD}INFO: Please copy/paste the ${myPlaceConfigAA} into MyPlace JASON Config Editor manually${TNRM}"
                  exit 1
               elif expr "${INPUT}" : '[./a-zA-Z0-9]*/config.json$' >/dev/null; then
                  if [ -f "${INPUT}" ]; then
                     homebridgeConfigJson="${INPUT}"
                     break
                  else
                     echo ""
                     echo "${TPUR}WARNING: No such file exits!${TNRM}"
                     echo ""
                     INPUT=""
                  fi
               else
                  echo ""
                  echo "${TPUR}WARNING: Wrong format for file path for Homebridge config.json!${TNRM}"
                  echo ""
                  INPUT=""
               fi
           done
         fi
         if [ -f "${homebridgeConfigJson}" ]; then
            if [ -z "${INPUT}" ]; then
               echo ""
               echo "${TLBL}INFO: The Homebridge config.json found: ${homebridgeConfigJson}${TNRM}"
               echo ""
            else
               echo ""
               echo "${TLBL}INFO: The Homebridge config.json specified: ${homebridgeConfigJson}${TNRM}"
               echo ""
            fi
            # expand the json just in case it is in compact form
            config=$( jq '.' "${homebridgeConfigJson}" )
            checkForPlatformMyPlaceInHomebridgeConfigJson
            if [ -z "${validFile}" ]; then
               echo ""
               echo "${TRED}ERROR: no MyPlace Config found in \"${homebridgeConfigJson}\"! Please ensure that Homebridge-myplace plugin is installed${TNRM}"
               echo "${TLBL}INFO: ${myPlaceConfigAA} was created but not copied to Homebridge-MyPlace JASON Config Editor!"
               echo "      Please copy/paste the ${myPlaceConfigAA} into MyPlace JASON Config Editor manually${TNRM}"
               echo "${myPlaceConfigAA}" | sudo tee "$HOME/myPlaceConfigAA.json" > /dev/null
               exit 1
            fi
         fi
      ;;
   esac
}

function extractMyPlaceDevices()
{
   # Extract MyPlace devices (name and devices) information
   myPlaceDevices="{}"
   devices=$( echo "${myPlaceConfig}" | jq '.devices' )
   if [ "${devices}" != "null" ]; then
      myPlaceDevices=$( echo "${myPlaceDevices}" | jq ".devices += $devices" )
   fi
}

function updateMyPlaceDevices()
{
   # To update the parmaters of MyPlace devices and is only call for nonUI case
   # The parameters of MyPlace devices are updated by config.schema for customUI case

   # update device1
   ipAddress1="$(echo "${AAIP}" | cut -d":" -f1)"
   port1="$(echo "${AAIP}" | cut -d":" -f2)"
   myPlaceDevices=$( echo "${myPlaceDevices}" | jq ".devices[0].name |= \"${AAname}\"" \
                                              | jq ".devices[0].ipAddress |= \"${ipAddress1}\"" \
                                              | jq ".devices[0].port |= ${port1}" \
                                              | jq ".devices[0].extraTimers |= ${extraTimers1}" \
                                              | jq ".devices[0].debug |= ${AAdebug}" )

   # update/insert/remove device2  
   ipAddress2="$(echo "${AAIP2}" | cut -d":" -f1)"
   port2="$(echo "${AAIP2}" | cut -d":" -f2)"
   # update/insert device2  
   if [ -n "${AAname2}" ]; then
      myPlaceDevices=$( echo "${myPlaceDevices}" | jq ".devices[1].name |= \"${AAname2}\"" \
                                                 | jq ".devices[1].ipAddress |= \"${ipAddress2}\"" \
                                                 | jq ".devices[1].port |= ${port2}" \
                                                 | jq ".devices[1].extraTimers |= ${extraTimers2}" \
                                                 | jq ".devices[1].debug |= ${AAdebug2}" )
   else # remove device2
      myPlaceDevices=$( echo "${myPlaceDevices}" | jq "del(.devices[1])" )
   fi

   # update/insert device3  
   ipAddress3="$(echo "${AAIP3}" | cut -d":" -f1)"
   port3="$(echo "${AAIP3}" | cut -d":" -f2)"
   # update/insert device2  
   if [ -n "${AAname3}" ]; then
      myPlaceDevices=$( echo "${myPlaceDevices}" | jq ".devices[2].name |= \"${AAname3}\"" \
                                                 | jq ".devices[2].ipAddress |= \"${ipAddress3}\"" \
                                                 | jq ".devices[2].port |= ${port3}" \
                                                 | jq ".devices[2].extraTimers |= ${extraTimers3}" \
                                                 | jq ".devices[2].debug |= ${AAdebug3}" )
   else # remove device2
      myPlaceDevices=$( echo "${myPlaceDevices}" | jq "del(.devices[2])" )
   fi
}

function extractMyPlaceConfigFromConfigJson()
{
   noOfPlatforms=$(( $( echo "${config}" | jq ".platforms|keys" | wc -w) - 2 ))
   for ((i=0; i<noOfPlatforms; i++)); do
      plaftorm=$( echo "${config}" | jq ".platforms[${i}].platform" )
      if [ "${plaftorm}" = "\"${myPlacePlatform}\"" ]; then
         myPlaceConfig=$( echo "${config}" | jq ".platforms[${i}]" )
         configMyPlaceLess=$( echo "${config}" | jq "del(.platforms[${i}])" )
         break
      fi
   done
}

function extractMyPlaceConfigNonAAandAccessoriesNonAA()
{
   myPlaceConfigNonAA="${myPlaceConfig}"
   presenceOfAccessories=$( echo "${myPlaceConfig}" | jq ".accessories" )
   if [ "${presenceOfAccessories}" != "null" ]; then
      noOfAccessories=$(( $( echo "${myPlaceConfig}" | jq ".accessories|keys" | wc -w) - 2 ))
      for (( i=0; i<noOfAccessories; i++ )); do
         myPlaceStateCmd=$( echo "${myPlaceConfig}" | jq ".accessories[${i}].state_cmd" | grep -n "homebridge-myplace" )
         # create the non-AA myPlaceConfigNonAA 
         if [ "${myPlaceStateCmd}" != "" ]; then
            myPlaceConfigNonAA=$( echo "${myPlaceConfigNonAA}" | jq "del(.accessories[${i}])" )
         else   # create the non-AA accessories
            accessoriesNonAA=$( echo "${myPlaceConfig}" | jq ".accessories[${i}]" )
            myPlaceAccessoriesAAwithNonAA=$( echo "${myPlaceAccessoriesAAwithNonAA}" | jq ".accessories += [${accessoriesNonAA}]" )
         fi
      done
   fi
}

function extractNonAAconstants()
{
   noOfConstants=$(( $( echo "${myPlaceConfigNonAA}" | jq ".constants|keys" | wc -w) - 2 ))
   for ((i=0; i<noOfConstants; i++)); do
      key=$( echo "${myPlaceConfigNonAA}" | jq ".constants[${i}].key" )
      key=${key//\"/}
      keyUsed=$( echo "${accessoriesNonAA}" | grep -n "${key}" | grep -v 'key' | head -n 1 | cut -d":" -f1 )
      if [ -n "${keyUsed}" ]; then
         constantsNonAA=$( echo "${myPlaceConfigNonAA}" | jq ".constants[${i}]" )
         myPlaceConstantsAAwithNonAA=$( echo "${myPlaceConstantsAAwithNonAA}" | jq ".constants += [${constantsNonAA}]" )
      fi
   done
}

function extractNonAAqueueTypes()
{
   noOfQueues=$(( $( echo "${myPlaceConfigNonAA}" | jq ".queueTypes|keys" | wc -w) - 2 ))
   for ((i=0; i<noOfQueues; i++)); do
      queue=$( echo "${myPlaceConfigNonAA}" | jq ".queueTypes[${i}].queue" )
      queueUsed=$( echo "${accessoriesNonAA}" | grep -n "${queue}" | head -n 1 )
      if [ -n "${queueUsed}" ]; then
         queueTypesNonAA=$( echo "${myPlaceConfigNonAA}" | jq ".queueTypes[${i}]" )
         myPlaceQueueTypesAAwithNonAA=$( echo "${myPlaceQueueTypesAAwithNonAA}" | jq ".queueTypes += [${queueTypesNonAA}]" )
      fi
   done
}

function extractMyPlaceMiscKeys()
{
   # Extract any misc MyPlace Keys used by non-AA accessories
   myPlaceMiscKeys="${myPlaceConfigNonAA}"
   keys=$( echo "${myPlaceConfigNonAA}" | jq ".|keys" )
   noOfKeys=$(( $(echo "${keys}" | wc -w) - 2 ))
   for ((i=0; i<noOfKeys; i++)); do
      key=$( echo "${keys}" | jq ".[${i}]" )
      key=${key//\"/}
      if [[ "${key}" = "title" || "${key}" = "name" || "${key}" = "devices" || "${key}" = "platform" || "${key}" = "debug" || "${key}" = "outputConstants" || "${key}" = "statusMsg" || "${key}" = "timeout" || "${key}" = "stateChangeResponseTime" || "${key}" = "constants" || "${key}" = "queueTypes" || "${key}" = "accessories" ]]; then
         myPlaceMiscKeys=$( echo "${myPlaceMiscKeys}" | jq "del(.${key})" )
      fi
   done
}

function extractNonAAaccessoriesrConstantsQueueTypesMisc()
{
   # this function should only be called after the AA constants, queueTypes and accessories are created
   # extract non-AA config from ${myPlaceConfig} and concatenate non-AA accessories to AA accessories
   # then extract misc. keys from non-AA config
   myPlaceAccessoriesAAwithNonAA="${myPlaceAccessoriesAA}"
   extractMyPlaceConfigNonAAandAccessoriesNonAA
   extractMyPlaceMiscKeys

   # extract and concatenate the non-AA constants and non-AA queueTypes to AA's if there are non-AA accessories
   myPlaceConstantsAAwithNonAA="${myPlaceConstantsAA}"
   myPlaceQueueTypesAAwithNonAA="${myPlaceQueueTypesAA}"
   if [ -n "${accessoriesNonAA}" ]; then
      extractNonAAconstants
      extractNonAAqueueTypes
   fi

}

function assembleMyPlaceConfigAA()
{
   myPlaceConfigAA="{}" 
   myPlaceConfigAA=$( echo "${myPlaceConfigAA}" | jq ".name += \"MyPlace\"" \
                                                | jq ". += ${myPlaceDevices}" \
                                                | jq ". += ${myPlaceBasicKeys}" \
                                                | jq ". += ${myPlaceConstantsAA}" \
                                                | jq ". += ${myPlaceQueueTypesAA}" \
                                                | jq ". += ${myPlaceAccessoriesAA}" \
                                                | jq ".platform += \"MyPlace\"" )
}

function assembleMyPlaceConfigAAwithNonAA()
{
   myPlaceConfigAAwithNonAA="{}" 
   myPlaceConfigAAwithNonAA=$( echo "${myPlaceConfigAAwithNonAA}" | jq ".name += \"MyPlace\"" \
                                                                  | jq ". += ${myPlaceDevices}" \
                                                                  | jq ". += ${myPlaceBasicKeys}" \
                                                                  | jq ". += ${myPlaceConstantsAAwithNonAA}" \
                                                                  | jq ". += ${myPlaceQueueTypesAAwithNonAA}" \
                                                                  | jq ". += ${myPlaceAccessoriesAAwithNonAA}" \
                                                                  | jq ".platform += \"MyPlace\"" \
                                                                  | jq ". += ${myPlaceMiscKeys}" )
}

function getGlobalNodeModulesPathForFile()
{
   file="$1"
   fullPath=""

   for ((tryIndex = 1; tryIndex <= 8; tryIndex ++)); do
      case $tryIndex in
         1)
            foundPath=$(find /var/lib/hoobs 2>&1|grep -v find|grep -v System|grep -v cache|grep node_modules|grep myplace|grep "/${file}$")
            fullPath=$(echo "${foundPath}"|head -n 1)
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         2)
            foundPath=$(npm root -g)
            fullPath="${foundPath}/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         3)
            fullPath="/var/lib/homebridge/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         4)
            fullPath="/var/lib/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         5)
            fullPath="/usr/local/lib/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         6)
            fullPath="/usr/lib/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         7)
            fullPath="/opt/homebrew/lib/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
         8)
            fullPath="/opt/homebridge/lib/node_modules/homebridge-myplace/${file}"
            if [ -f "${fullPath}" ]; then
               return
            else
               fullPath=""
            fi
         ;;
      esac
   done
}

function getHomebridgeConfigJsonPath()
{
   fullPath=""
   # Typicall HOOBS installation has its config.json root path same as the root path of "MyPlace.sh"
   # The typical full path to the "MyPlace.sh" script is .../hoobs/<bridge>/node_modules/homebridge-myplace/MyPlace.sh
   # First, determine whether this is a HOOBS installation
   Hoobs=$( echo "$MYPLACE_SH_PATH" | grep "/hoobs/" )
   if [ -n "${Hoobs}" ]; then
      fullPath="${MYPLACE_SH_PATH%/*/*/*}/config.json"
      if [ -f "${fullPath}" ]; then
         checkForMyPlacePlatformNameInFile
         if [ -z "${myPlacePlatformFound}" ]; then
            fullPath=""
         fi
         return
      fi
   fi

   for ((tryIndex = 1; tryIndex <= 6; tryIndex ++)); do
      case $tryIndex in
         1)
            # Typical RPi, Synology NAS installations have this path to config.json
            fullPath="/var/lib/homebridge/config.json"
            if [ -f "${fullPath}" ]; then
               checkForMyPlacePlatformNameInFile
               if [ -n "${myPlacePlatformFound}" ]; then
                  return
               else
                  fullPath=""
               fi
            fi
         ;;
         2)
            # Typical Mac installation has this path to config.json
            fullPath="$HOME/.homebridge/config.json"
            if [ -f "${fullPath}" ]; then
               checkForMyPlacePlatformNameInFile
               if [ -n "${myPlacePlatformFound}" ]; then
                  return
               else
                  fullPath=""
               fi
            fi
         ;;
         3)
            foundPath=$(find /usr/local/lib 2>&1|grep -v find|grep -v System|grep -v cache|grep -v hassio|grep -v node_modules|grep "/config.json$")
            noOfInstances=$(echo "${foundPath}"|wc -l)
            for ((i = 1; i <= noOfInstances; i ++)); do
               fullPath=$(echo "${foundPath}"|sed -n "${i}"p)
               if [ -f "${fullPath}" ]; then
                  checkForMyPlacePlatformNameInFile
                  if [ -n "${myPlacePlatformFound}" ]; then
                     return
                  else
                     fullPath=""
                  fi
               fi
            done
         ;;
         4)
            foundPath=$(find /usr/lib 2>&1|grep -v find|grep -v System|grep -v cache|grep -v hassio|grep -v node_modules|grep "/config.json$")
            noOfInstances=$(echo "${foundPath}"|wc -l)
            for ((i = 1; i <= noOfInstances; i ++)); do
               fullPath=$(echo "${foundPath}"|sed -n "${i}"p)
               if [ -f "${fullPath}" ]; then
                  checkForMyPlacePlatformNameInFile
                  if [ -n "${myPlacePlatformFound}" ]; then
                     return
                  else
                     fullPath=""
                  fi
               fi
            done
         ;;
         5)
            foundPath=$(find /var/lib 2>&1|grep -v find|grep -v hoobs|grep -v System|grep -v cache|grep -v hassio|grep -v node_modules|grep "/config.json$")
            noOfInstances=$(echo "${foundPath}"|wc -l)
            for ((i = 1; i <= noOfInstances; i ++)); do
               fullPath=$(echo "${foundPath}"|sed -n "${i}"p)
               if [ -f "${fullPath}" ]; then
                  checkForMyPlacePlatformNameInFile
                  if [ -n "${myPlacePlatformFound}" ]; then
                     return
                  else
                     fullPath=""
                  fi
               fi
            done
         ;;
         6)
            foundPath=$(find /opt 2>&1|grep -v find|grep -v hoobs|grep -v System|grep -v cache|grep -v hassio|grep -v node_modules|grep "/config.json$")
            noOfInstances=$(echo "${foundPath}"|wc -l)
            for ((i = 1; i <= noOfInstances; i ++)); do
               fullPath=$(echo "${foundPath}"|sed -n "${i}"p)
               if [ -f "${fullPath}" ]; then
                  checkForMyPlacePlatformNameInFile
                  if [ -n "${myPlacePlatformFound}" ]; then
                     return
                  else
                     fullPath=""
                  fi
               fi
            done
         ;;
      esac
   done
}

function checkForPlatformMyPlaceInHomebridgeConfigJson()
{
   validFile=""
   for ((tryIndex = 1; tryIndex <= 2; tryIndex ++)); do
      case $tryIndex in
         1)
            validFile=$( echo "${config}" | grep -n "${myPlacePlatform1}" | cut -d":" -f1)
            if [ -n "${validFile}" ]; then
               myPlacePlatform="${myPlacePlatform1}"
               return
            fi
         ;;
         2)
            validFile=$( echo "${config}" | grep -n "${myPlacePlatform2}" | cut -d":" -f1)
            if [ -n "${validFile}" ]; then
               myPlacePlatform="${myPlacePlatform2}"
               return
            fi
         ;;
      esac
   done
}

function checkForMyPlacePlatformNameInFile()
{
   myPlacePlatformFound=""

   for ((Index = 1; Index <= 2; Index ++)); do
      case $Index in
         1)
           
            myPlacePlatformFound=$(grep "\"${myPlacePlatform1}\"" "${fullPath}")
            if [ -n "${myPlacePlatformFound}" ]; then
               return
            fi
         ;;
         2)
            myPlacePlatformFound=$(grep "\"${myPlacePlatform2}\"" "${fullPath}")
            if [ -n "${myPlacePlatformFound}" ]; then
               return
            fi
         ;;
      esac
   done
}

function writeToHomebridgeConfigJson()
{
   # This is only call for nonUI case
   # Writing the created "${myPlaceConfigAAwithNonAA}" to "${configMyPlaceLess}" to create "${configNew}"
   # before copying to Homebridge config.json

   configNew=$( echo "${configMyPlaceLess}" | jq ".platforms += [${myPlaceConfigAAwithNonAA}]" )
   rc=$?
   if [ "${rc}" != "0" ]; then
      echo "${TRED}${BOLD}ERROR: Writing of created MyPlace config to config.json failed!${TNRM}"
      echo "${TLBL}${BOLD}INFO: Instead you can copy/paste the content of \"$HOME/myPlaceConfigAAwithNonAA.json\" into MyPlace JASON Config editor.${TNRM}"
      echo "${myPlaceConfigAAwithNonAA}" | sudo tee "$HOME/myPlaceConfigAAwithNonAA.json"
      exit 1
   fi

   # Copy the "${configNew}" to Homebridge config.json
   fname=$( find "${homebridgeConfigJson}" -user "$USER" );
   if [ "${fname}" = "${homebridgeConfigJson}" ]; then
      echo "${configNew}" | tee "${homebridgeConfigJson}" > /dev/null
      rc=$?
   else
      echo "${configNew}" | sudo tee "${homebridgeConfigJson}" > /dev/null
      rc=$?
   fi
}

# main starts here

if [ -z "${MYPLACE_SH_PATH}" ]; then UIversion="nonUI"; fi

case $UIversion in
   customUI )
      if expr "${AAIP}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
         AAIP="${AAIP}:2025"
      else
         if expr "${AAIP}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
            echo ""
         else
            echo "ERROR: the specified IP address ${AAIP} is in wrong format"
            exit 1
         fi
      fi

      if [[ -n "${AAIP2}" && "${AAIP2}" != "undefined" ]]; then
         if expr "${AAIP2}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
            AAIP2="${AAIP2}:2025"
         else
            if expr "${AAIP2}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
               echo ""
            else
               echo "ERROR: the specified IP address ${AAIP2} is in wrong format"
               exit 1
            fi
         fi
      else
         AAIP2=""
         AAname2=""
      fi

      if [[ -n "${AAIP3}" && "${AAIP3}" != "undefined" ]]; then
         if expr "${AAIP3}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
            AAIP3="${AAIP3}:2025"
         else
            if expr "${AAIP3}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
               echo ""
            else
               echo "ERROR: the specified IP address ${AAIP3} is in wrong format"
               exit 1
            fi
         fi
      else
         AAIP3=""
         AAname3=""
      fi
   ;;
   nonUI )
      AAIP=""
      AAIP2=""
      AAIP3=""

      until [ -n "${AAIP}" ]; do
         echo "${TYEL}Please enter the name (default: Aircon) and IP address of your AdvantageAir system:"
         read -r -p "Name: ${TNRM}" AAname
         if [ -z "${AAname}" ]; then AAname="Aircon"; fi
         read -r -p "${TYEL}IP address (xxx.xxx.xxx.xxx or xxx.xxx.xxx.xxx:xxxx): ${TNRM}" INPUT
         if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
            AAIP="${INPUT}:2025"
         else
            if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
               PORT=$(echo "${INPUT}" | cut -d':' -f2)
               if [ -n "${PORT}" ]; then AAIP="${INPUT}"; else AAIP="${INPUT}2025"; fi
            else
               echo ""
               echo "${TPUR}WARNING: Wrong format for an IP address! Please enter again!${TNRM}"
               echo ""
            fi
         fi
      done

      read -r -p "${TYEL}Include extra fancy timers to turn-on the Aircon in specific mode: Cool, Heat or Vent? (y/n, default=n):${TNRM} " INPUT
      if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" ]]; then
         extraTimers1="true"
      else
         extraTimers1="false"
      fi

      AAdebug="false"
      read -r -p "${TYEL}Enable debug? (y/n, default=n): ${TNRM}" INPUT
      if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" || "${INPUT}" = "true" ]]; then AAdebug="true"; fi

      until [ -n "${AAIP2}" ]; do
         echo ""
         echo "${TYEL}Please enter the name and IP address of your 2nd AdvantageAir System if any. Just hit 'enter' if none:"
         read -r -p "Name: ${TNRM}" AAname2
         if [ -z "${AAname2}" ]; then
            break
         fi
         read -r -p "${TYEL}IP address (xxx.xxx.xxx.xxx or xxx.xxx.xxx.xxx:xxxx): ${TNRM}" INPUT
         if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
            AAIP2="${INPUT}:2025"
         else
            if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
               PORT=$(echo "${INPUT}" | cut -d':' -f2)
               if [ -n "${PORT}" ]; then AAIP2="${INPUT}"; else AAIP2="${INPUT}2025"; fi
            else
               echo ""
               echo "${TPUR}WARNING: Wrong format for an IP address! Please enter again!${TNRM}"
               echo ""
            fi
         fi
      done
      if [ -n "${AAIP2}" ]; then
         read -r -p "${TYEL}Include extra fancy timers to turn-on the Aircon in specific mode: Cool, Heat or Vent? (y/n, default=n):${TNRM} " INPUT
         if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" ]]; then
            extraTimers2="true"
         else
            extraTimers2="false"
         fi

         AAdebug2="false"
         read -r -p "${TYEL}Enable debug? (y/n, default=n): ${TNRM}" INPUT
         if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" || "${INPUT}" = "true" ]]; then AAdebug2="true"; fi
      fi

      if [ -n "${AAIP2}" ]; then
         until [ -n "${AAIP3}" ]; do
            echo ""
            echo "${TYEL}Please enter the name and IP address of your 3rd AdvantageAir System if any. Just hit 'enter' if none:"
            read -r -p "Name: ${TNRM}" AAname3
            if [ -z "${AAname3}" ]; then
               break
            fi
            read -r -p "${TYEL}IP address (xxx.xxx.xxx.xxx or xxx.xxx.xxx.xxx:xxxx): ${TNRM}" INPUT
            if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$' >/dev/null; then
               AAIP3="${INPUT}:2025"
            else
               if expr "${INPUT}" : '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*:[0-9]*$' >/dev/null; then
                  PORT=$(echo "${INPUT}" | cut -d':' -f2)
                  if [ -n "${PORT}" ]; then AAIP3="${INPUT}"; else AAIP3="${INPUT}2025"; fi
               else
                  echo ""
                  echo "${TPUR}WARNING: Wrong format for an IP address! Please enter again!${TNRM}"
                  echo ""
               fi
            fi
         done
         if [ -n "${AAIP3}" ]; then
            read -r -p "${TYEL}Include extra fancy timers to turn-on the Aircon in specific mode: Cool, Heat or Vent? (y/n, default=n):${TNRM} " INPUT
            if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" ]]; then
               extraTimers3="true"
            else
               extraTimers3="false"
            fi

            AAdebug3="false"
            read -r -p "${TYEL}Enable debug? (y/n, default=n): ${TNRM}" INPUT
            if [[ "${INPUT}" = "y" || "${INPUT}" = "Y" || "${INPUT}" = "true" ]]; then AAdebug3="true"; fi
         fi
      fi

      # get the full path to MyPlace.sh
      MYPLACE_SH_PATH=""
      getGlobalNodeModulesPathForFile "MyPlace.sh"
      if [ -n "${fullPath}" ]; then
         MYPLACE_SH_PATH=${fullPath}
         echo ""
         echo "${TLBL}INFO: MyPlace.sh found: ${MYPLACE_SH_PATH}${TNRM}"
      fi

      if [ -z "${MYPLACE_SH_PATH}" ]; then
         MYPLACE_SH_PATH=""
         until [ -n "${MYPLACE_SH_PATH}" ]; do
            echo ""
            echo "${TYEL}Please enter the full path of where the MyPlace.sh is installed in your system"
            echo "The file path format should be : /*/*/*/node_modules/homebridge-myplace/MyPlace.sh${TNRM}"
            read -r -p "${BOLD}> ${TNRM}" INPUT
            if expr "${INPUT}" : '/[a-zA-Z0-9/_]*/node_modules/homebridge-myplace/MyPlace.sh$' >/dev/null; then
               if [ -f "${INPUT}" ]; then
                  MYPLACE_SH_PATH=${INPUT}
                  echo ""
                  echo "${TLBL}INFO: MyPlace.sh specified: ${MYPLACE_SH_PATH}${TNRM}"
                  break
               else
                  echo ""
                  echo "${TPUR}WARNING: file ${INPUT} not found${TNRM}"
               fi
            else
               echo ""
               echo "${TPUR}WARNING: file ${INPUT} is in wrong format${TNRM}"
            fi
         done
      fi
   ;;
esac

if [ -n "${AAIP}" ]; then noOfTablets=1; fi
if [ -n "${AAIP2}" ]; then noOfTablets=2; fi
if [ -n "${AAIP3}" ]; then noOfTablets=3; fi

for ((n=1; n<=noOfTablets; n++)); do

   if [ "${n}" = "1" ]; then
      ip="\${AAIP}"
      IPA="${AAIP}"
      nameA="${AAname}"
      extraTimers="${extraTimers1}"
      debug="${AAdebug}"
      queue="AAA"
   fi
   if [ "${n}" = "2" ]; then
      ip="\${AAIP2}"
      IPA="${AAIP2}"
      nameA="${AAname2}"
      extraTimers="${extraTimers2}"
      debug="${AAdebug2}"
      queue="AAB"
   fi
   if [ "${n}" = "3" ]; then
      ip="\${AAIP3}"
      IPA="${AAIP3}"
      nameA="${AAname3}"
      extraTimers="${extraTimers3}"
      debug="${AAdebug3}"
      queue="AAC"
   fi

   if [[ "${n}" = "1" && "${UIversion}" = "nonUI" ]]; then
      echo ""
      if [ "${noOfTablets}" = "1" ]; then echo "${TLBL}${BOLD}INFO: This process may take up to 1 minute!${TNRM}"; fi
      if [ "${noOfTablets}" = "2" ]; then echo "${TLBL}${BOLD}INFO: This process may take up to 2 minutes!${TNRM}"; fi
      if [ "${noOfTablets}" = "3" ]; then echo "${TLBL}${BOLD}INFO: This process may take up to 3 minutes!${TNRM}"; fi
   fi

   if [ "${UIversion}" = "nonUI" ]; then
      echo "${TLBL}INFO: Fetching and processing data from your AdvantageAir system (${nameA} ${IPA}).... ${TNRM}"
      echo ""
      echo "${TLBL}INFO: extraTimers=${extraTimers}${TNRM}"
   fi

   myAirData=$(curl -s -g --max-time 45 --fail --connect-timeout 45 "http://${IPA}/getSystemData")
   #
   if [ -z "$myAirData" ]; then
      echo "${TRED}ERROR: AdvantageAir system is inaccessible or your IP address ${IPA} is invalid!${TNRM}"
      exit 1
   fi

   #
   sysName=$(echo "$myAirData"|jq -e ".system.name" | sed 's/ /_/g' | sed s/[\'\"]//g)
   if [ -z "${sysName}" ]; then
      echo "${TRED}ERROR: jq failed! Please make sure that jq is installed!${TNRM}"
      exit 1
   fi
   sysType=$(echo "$myAirData" | jq -e ".system.sysType" | sed 's/ /_/g' | sed 's/\"//g')
   tspModel=$(echo "$myAirData" | jq -e ".system.tspModel" | sed 's/ /_/g' | sed 's/\"//g')

   hasAircons=$(echo "$myAirData"|jq -e ".system.hasAircons")
   noOfAircons=$(echo "$myAirData"|jq -e ".system.noOfAircons")
   hasLights=$(echo "$myAirData"|jq -e ".system.hasLights")
   hasThings=$(echo "$myAirData"|jq -e ".system.hasThings")

   # Read the existing Homebridge config.json file
   readHomebridgeConfigJson

   # Extract MyPlace platform
   extractMyPlaceConfigFromConfigJson

   # Create the ${myPlaceBasicKeys}
   # First check whether the original MyPlace platform has its "debug=true" for nonAA system, if so leave that as "true"
   debugPresence=$( echo "${myPlaceConfig}" | jq ".constants" | grep -v ":2025-debug" | grep "\-debug" )
   debugMyPlace=false
   if [ -n "${debugPresence}" ]; then
      debugMyPlace=true
   else
      if [[ "${AAdebug}" = "true" || "${AAdebug2}" = "true" ||"${AAdebug3}" = "true" ]]; then
         debugMyPlace=true
      fi
   fi
   myPlaceBasicKeys

   # Create the ${myPlaceConstantsAA} and ${myPlaceQueueTypesAA}
   myPlaceConstants
   myPlaceQueueTypes

   # Create the myPlaceModelQueue for this AA system
   myPlaceModelQueue

   # Create the $myPlaceAccessoriesAA
   # Aircon systems
   if [ "$hasAircons" = true ]; then
      for (( a=1;a<=noOfAircons;a++ )); do
         ac=$( printf "ac%1d" "$a" )
         aircon=$(echo "$myAirData" | jq -e ".aircons.${ac}.info")
         if [ "${aircon}" != "null" ]; then

            # check that the system has tempSensors, if so, set zoneSetTemp="true" 
            zoneSetTemp="false"
            nZones=$(echo "$myAirData" | jq -e ".aircons.${ac}.info.noOfZones")
            for (( b=1;b<=nZones;b++ )); do
               zone="${b}"
               zoneStr=$( printf "z%02d" "${zone}" )
               rssi=$(echo "$myAirData" | jq -e ".aircons.${ac}.zones.${zoneStr}.rssi")
               if [ "${rssi}" != "0" ]; then
                  zoneSetTemp="true"
                  break
               fi
            done

            if [ "${a}" -ge "2" ]; then nameA="${nameA} ${ac}"; fi
            if [ "${zoneSetTemp}" = "true" ]; then zoneA=""; else zoneA="noOtherThermostat"; fi
            # use only alphanumeric, space, and apostrophe characters for name 
            #name=$(echo "$myAirData" | jq -e ".aircons.${ac}.info.name" | sed 's/\"//g')

            # Creating Aircon config
            myPlaceThermostat "${nameA}" "${zoneA}"
            myPlaceFanSwitch "${nameA} Fan"
            myPlaceTimerLightbulb "${nameA} Timer" "timer"
            if [ "${extraTimers}" = "true" ]; then
               myPlaceTimerLightbulb "${nameA} Fan Timer" "fanTimer"
               myPlaceTimerLightbulb "${nameA} Cool Timer" "coolTimer"
               myPlaceTimerLightbulb "${nameA} Heat Timer" "heatTimer"
            fi

            # Creating Zones config
            nZones=$(echo "$myAirData" | jq -e ".aircons.${ac}.info.noOfZones")
            myZoneValue=$(echo "$myAirData" | jq -e ".aircons.${ac}.info.myZone")
            for (( b=1;b<=nZones;b++ )); do
               zone="${b}"
               zoneStr=$( printf "z%02d" "${zone}" )
               # use only alphanumeric, space, and apostrophe characters for name 
               nameZ=$(echo "$myAirData" |jq -e ".aircons.${ac}.zones.${zoneStr}.name" | sed 's/\"//g')
               rssi=$(echo "$myAirData" | jq -e ".aircons.${ac}.zones.${zoneStr}.rssi")
               if [ "${rssi}" = "0" ]; then
                  myPlaceZoneFan "${nameZ} Zone"
               elif [ "${myZoneValue}" != "0" ]; then
                  myPlaceZoneFanv2 "${nameZ} Zone"
               else
                  myPlaceZoneFanv2noRotationDirection "${nameZ} Zone"
               fi
            done
         fi
      done
   fi

   # Lightings
   if [ "$hasLights" = true ]; then
      eval "idArray=($( echo "$myAirData" | jq -e ".myLights.lights" | grep \"id\" | cut -d":" -f2 | sed 's/[,]//g' ))"
      noOfElements=${#idArray[*]}
      for (( i=0;i<noOfElements;i++ ));
      do
         id="\"${idArray[$i]}\""
         name=$(echo "$myAirData" | jq -e ".myLights.lights.${id}.name" | sed 's/\"//g')
         value=$(echo "$myAirData" | jq -e ".myLights.lights.${id}.value ")

         if [ "${name:(-4)}" = " Fan" ]; then 
            #  From v1.0.6 onwards, a light switch with name ending with " Fan" is regarded as a switch for a fan.
            myPlaceFanNoRotationSpeed "${name}" "${id}"
         else
            if [ "${value}" = "null" ]; then
               myPlaceLightbulbNoDimmer "${name}" "${id}"
            else
               myPlaceLightbulbWithDimmer "${name}" "${id}"
            fi         
         fi            
      done
   fi

   # Things - Garage and blinds 
   if [ "$hasThings" = true ]; then
      eval "idArray=($( echo "$myAirData" | jq -e ".myThings.things" | grep \"id\" | cut -d":" -f2 | sed 's/[,]//g' ))"
      noOfElements=${#idArray[*]}
      for (( i=0;i<noOfElements;i++ ));
      do
         id="\"${idArray[$i]}\""
         name=$(echo "$myAirData" | jq -e ".myThings.things.${id}.name" | sed 's/\"//g')
         channelDipState=$(echo "$myAirData" | jq -e ".myThings.things.${id}.channelDipState" | sed 's/\"//g')
         if [ "${channelDipState}" = "3" ]; then
            myPlaceGarageDoorOpener "${name}" "${id}"
         elif [[ "${channelDipState}" = "1" || "${channelDipState}" = "2" ]]; then
            myPlaceWindowCovering "${name}" "${id}"
         fi
      done
   fi

done

# Extract all non-AA related MyPlace accessories, constants and queueTypes
extractNonAAaccessoriesrConstantsQueueTypesMisc

# Extract the MyPlace "devices" keys
extractMyPlaceDevices
if [ "${UIversion}" = "nonUI" ]; then 
   updateMyPlaceDevices
fi

# Assemble a complete MyPlace configuration file for AA device(s)
assembleMyPlaceConfigAA

# Assemble a complete MyPlace configuration file for AA devices(s) with the extracted non-AA devices (if any).
assembleMyPlaceConfigAAwithNonAA

# Write the assembled AA + non-AA MyPlace configuration into the Homebridge config.json
if [ "${UIversion}" = "nonUI" ]; then
   writeToHomebridgeConfigJson

   if [ "${rc}" = "0" ]; then
      echo "${TGRN}${BOLD}DONE! Run CheckConfig then restart Homebridge or HOOBS.${TNRM}"
      echo ""
      echo "${TYEL}To run CheckConfig, please copy/paste and run the following command to check whether the MyPlace configuration meets all the requirements${TNRM}"
      echo "${MYPLACE_SH_PATH%/*}/CheckConfig.sh"
   else
      # Copying of the new config.json to homebridge config.json failed so restore the homebridge config.json from backup
      echo "${TRED}${BOLD}ERROR: Copying of created new MyPlace Config to Homebridge config.json failed! Original config.json will be restored.${TNRM}"
      echo "${config}" | sudo tee "${homebridgeConfigJson}" > /dev/null
      echo "${TLBL}${BOLD}INFO: Instead you can copy/paste the content of \"$HOME/myPlaceConfigAAwithNonAA.json\" into MyPlace JASON Config editor.${TNRM}"
      echo "${myPlaceConfigAAwithNonAA}" | sudo tee "$HOME/myPlaceConfigAAwithNonAA.Json" > /dev/null
   fi
else
   # for customUI case, send the new MyPlace pluginConfig to index.html to be merged to config.json using homebridge-ui-utils
   echo "DONE;${myPlaceConfigAAwithNonAA}"
fi

exit 0
