#!/bin/bash
# Copyright (C) 2024 MOXA Inc. All rights reserved.
# This software is distributed under the terms of the MOXA SOFTWARE NOTICE.
# See the file LICENSE for details.
#
# Name:
#       MOXA Power Input State Tool for DA Series
#
# Authors:
#       2024    Elvis Yao <ElvisCW.Yao@moxa.com>
#

source "/usr/lib/mx-gpio-lib"
source "/usr/lib/mx-common-lib"

MODEL_NAME=""
PWR_STATE_STR=("connected" "disconnected")
PWR_STATE_STR_LOW_ACT=("disconnected" "connected")
NUM_OF_PWR=""
NUM_OF_PWR_STATE=${#PWR_STATE_STR[@]}
TARGET_PWR_PORT=""
TARGET_STATE=""
TARGET_OPCODE=0
TARGET_GET_PWR_STATE_OPCODE=1
LOW_ACT=0

OS_ID="$(awk -v opt="ID" -F= '$1==opt { print $2 ;}' /etc/os-release | tr -d '"')"

# DA-681C settings
function DA681C::profile() {
        PWR_IT87_GPIO_TBL=(80 81)
        LOW_ACT="1"
}

function DA681C::init() {
        NUM_OF_PWR=${#PWR_IT87_GPIO_TBL[@]}
}

function DA681C::get_pwr_state() {
        get_pwr_state_it87 "$1"
}

# DA-682C settings
function DA682C::profile() {
        PWR_IT87_GPIO_TBL=(80 81)
        LOW_ACT="1"
}

function DA682C::init() {
        NUM_OF_PWR=${#PWR_IT87_GPIO_TBL[@]}
}

function DA682C::get_pwr_state() {
        get_pwr_state_it87 "$1"
}

# DA-820C settings
function DA820C::profile() {
        PWR_IT87_GPIO_TBL=(80 81)
        LOW_ACT="1"
}

function DA820C::init() {
        NUM_OF_PWR=${#PWR_IT87_GPIO_TBL[@]}
}

function DA820C::get_pwr_state() {
        get_pwr_state_it87 "$1"
}

# DA-820E settings
function DA820E::profile() {
        PWR_IT87_GPIO_TBL=(80 81)
        LOW_ACT="1"
}

function DA820E::init() {
        NUM_OF_PWR=${#PWR_IT87_GPIO_TBL[@]}
}

function DA820E::get_pwr_state() {
        get_pwr_state_it87 "$1"
}

# DA-680 settings
function DA680::profile() {
        PWR_IT87_GPIO_TBL=(80 81)
        LOW_ACT="1"
}

function DA680::init() {
        NUM_OF_PWR=${#PWR_IT87_GPIO_TBL[@]}
}

function DA680::get_pwr_state() {
        get_pwr_state_it87 "$1"
}

# Main functions
function get_pwr_state_it87() {
        local pwr_port

        pwr_port=${1}

        if [[ "${OS_ID}" == "centos" ]]; then
                get_pwr_state_it87_via_sysfs $pwr_port
        else
                get_pwr_state_it87_via_libgpiod $pwr_port
        fi
}

function get_pwr_state_it87_via_libgpiod() {
        local pwr_port
        local pwr_state
        local sio_gpio_pin
        local gpc_name
        local ret

        ret=0

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        pwr_port=${1}
        sio_gpio_pin=$(gpc_it8786_remap ${PWR_IT87_GPIO_TBL[$pwr_port]})
        gpc_name=$(gpio_get_gpiochip_name gpio_it87)
        [[ $? -ne 0 ]] && ret=1
        pwr_state=$(gpio_get_value_libgpiod $sio_gpio_pin $gpc_name)
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get power input state failed"
                exit $ret
        fi

        if [[ $LOW_ACT -eq 1 ]]; then
                echo "Current power input [${pwr_port}] is ${PWR_STATE_STR_LOW_ACT[$pwr_state]} state."
        else
                echo "Current power input [${pwr_port}] is ${PWR_STATE_STR[$pwr_state]} state."
        fi
}

function get_pwr_state_it87_via_sysfs() {
        local pwr_port
        local pwr_state
        local sio_gpio_pin

        if ! is_module_loaded gpio_it87; then
                echo "gpio_it87 driver is not loaded"
                exit 1
        fi

        pwr_port=${1}
        sio_gpio_pin=$(gpc_it8786 ${PWR_IT87_GPIO_TBL[$pwr_port]})
        [[ $? -ne 0 ]] && ret=1
        pwr_state=$(gpio_get_value_sysfs $sio_gpio_pin)
        [[ $? -ne 0 ]] && ret=1

        if [[ $ret -ne 0 ]]; then
                echo "Get power input state Failed"
                exit $ret
        fi

        if [[ $LOW_ACT -eq 1 ]]; then
                echo "Current power input [${pwr_port}] is ${PWR_STATE_STR_LOW_ACT[$pwr_state]} state."
        else
                echo "Current power input [${pwr_port}] is ${PWR_STATE_STR[$pwr_state]} state."
        fi
}

function load_model_name() {
        for name in $(get_model_name_from_dmi_type12); do
                if [[ "$(type -t "${name}::profile")" = 'function' ]]; then
                        MODEL_NAME="${name}"
                        break
                fi
        done

        if [[ -z "${MODEL_NAME}" ]]; then
                for name in $(get_model_name_from_dmi_type1); do
                        if [[ "$(type -t "${name}::profile")" = 'function' ]]; then
                                MODEL_NAME="${name}"
                                break
                        fi
                done
        fi

        if [[ -z "${MODEL_NAME}" ]]; then
                echo "Unsupported model"
                exit 38
        fi
}

function script_usage() {
        cat <<EOF
USAGE:
	mx-input-power-state -i <power_port>

OPTIONS:
	-i <power_port>
                Get power input port state <connected/disconnected>

EXAMPLE:
	Get power input port 0 state
	mx-input-power-state -i 0
EOF
}

function script_params() {
        if [[ $# -eq 0 ]]; then
                script_usage
                exit 1
        fi

        while getopts "hi:" opt; do
                case "${opt}" in
                i)
                        TARGET_PWR_PORT="$OPTARG"
                        TARGET_OPCODE=$((TARGET_OPCODE += 1))
                        ;;
                h)
                        script_usage
                        exit 0
                        ;;
                \?)
                        script_usage
                        exit 22
                        ;;
                :)
                        echo "Option -$OPTARG requires an argument." >&2
                        script_usage
                        exit 22
                        ;;
                esac
        done
}

function script_init() {
        load_model_name

        if [[ ! $(type -t "${MODEL_NAME}"::profile) == function ]]; then
                echo "${MODEL_NAME} profile function is not define"
                exit 1
        fi

        "${MODEL_NAME}"::profile

        if [[ ! $(type -t "${MODEL_NAME}"::init) == function ]]; then
                echo "${MODEL_NAME} init function is not define"
                exit 1
        fi

        "${MODEL_NAME}"::init
}

function verify_pwr_port() {
        if ! check_leading_zero_digit $TARGET_PWR_PORT; then
                echo "Invaild power input port format."
                exit 1
        fi

        if [[ $TARGET_PWR_PORT -lt 0 || $TARGET_PWR_PORT -ge $NUM_OF_PWR ]]; then
                echo "Invalid power input port."
                exit 1
        fi
}

function main() {
        script_params "$@"
        script_init

        case $TARGET_OPCODE in
        $TARGET_GET_PWR_STATE_OPCODE)
                verify_pwr_port

                if [[ ! $(type -t "${MODEL_NAME}"::get_pwr_state) == function ]]; then
                        echo "${MODEL_NAME} get_pwr_state function is not define"
                        exit 1
                fi

                "${MODEL_NAME}"::get_pwr_state $TARGET_PWR_PORT
                ;;
        *)
                script_usage
                exit 1
                ;;
        esac
}

main $@
