/**
 * @file cmd_bluetank.c
 * @author Shinichiro Nakamura
 * @brief bluetankコマンドの実装。
 * @details
 */

#include "cmd.h"
#include "ntlibc.h"

/**
 * @brief コマンドテーブル定義構造体。
 */
typedef struct {
    /**
     * @brief コマンド第１引数。
     */
    char *command;
    /**
     * @brief コマンド説明文。
     */
    char *description;
    /**
     * @brief コマンド第１引数が合致する場合に呼び出す関数。
     */
    void (*function)(cmd_env_t *env, int argc, char **argv);
} cmdtbl_t;

static void cmd_audio(cmd_env_t *env, int argc, char **argv);
static void cmd_system(cmd_env_t *env, int argc, char **argv);
static void cmd_help(cmd_env_t *env, int argc, char **argv);

/**
 * @brief コマンドテーブルの実装。
 */
static const cmdtbl_t cmdtbl[] = {
    {   "audio",    "Audio commands.",  cmd_audio   },
    {   "system",   "System commands.", cmd_system  },
    {   "help",     "Help commands.",   cmd_help    },
    {   0,          0,                  0           }
};

/**
 * @brief コマンド関数。
 * @details
 * ntshell_taskを使用するBSPは、cmd_executeの実装を提供する。
 * VT100のシーケンスコード解釈や環境設定は上位で行われている。
 *
 * @param env コマンド環境構造体。
 * @param argc パラメータ数。
 * @param argv パラメータ。
 */
void cmd_execute(cmd_env_t *env, int argc, char **argv)
{
    cmdtbl_t *p = (cmdtbl_t *)&cmdtbl[0];
    while (p->command != 0) {
        if (ntlibc_strcmp((const char *)argv[0], p->command) == 0) {
            p->function(env, argc, argv);
            return;
        }
        p++;
    }
    ntstdio_printf(CMD_NTSTDIO(env), "help: display help.\n");
}

/**
 * @brief audioコマンド関数。
 *
 * @param env コマンド環境構造体。
 * @param argc パラメータ数。
 * @param argv パラメータ。
 */
static void cmd_audio(cmd_env_t *env, int argc, char **argv)
{
    /*
     * [0]:audio, [1]:volume
     */
    if (argc > 1) {
        if (ntlibc_strcmp(argv[1], "volume") == 0) {
            static int volume = 0;  /**< @todo remove this variable. */
            switch (argc) {
                case 2:
                    // @todo Get current volume from the system.
                    ntstdio_printf(CMD_NTSTDIO(env), "%d\n", volume);
                    break;
                case 3:
                    // @todo Set the given volume to the system.
                    volume = ntlibc_atoi(argv[2]);
                    ntstdio_printf(CMD_NTSTDIO(env), "%d\n", volume);
                    break;
            }
            return;
        }
    }

    ntstdio_printf(CMD_NTSTDIO(env), "audio volume [value]\n");
}

/**
 * @brief systemコマンド関数。
 *
 * @param env コマンド環境構造体。
 * @param argc パラメータ数。
 * @param argv パラメータ。
 */
static void cmd_system(cmd_env_t *env, int argc, char **argv)
{
    /*
     * [0]:system, [1]:board
     */
    if (argc > 1) {
        if (ntlibc_strcmp(argv[1], "board") == 0) {
            switch (argc) {
                case 2:
                    ntstdio_printf(CMD_NTSTDIO(env), "BlueTank\n");
                    break;
            }
            return;
        }

        /*
         * [0]:system, [1]:version
         */
        if (ntlibc_strcmp(argv[1], "version") == 0) {
            switch (argc) {
                case 2:
                    ntstdio_printf(CMD_NTSTDIO(env), "0.0.1\n");
                    break;
            }
            return;
        }
    }

    ntstdio_printf(CMD_NTSTDIO(env), "system board\n");
    ntstdio_printf(CMD_NTSTDIO(env), "system version\n");
}

/**
 * @brief helpコマンド関数。
 *
 * @param env コマンド環境構造体。
 * @param argc パラメータ数。
 * @param argv パラメータ。
 */
static void cmd_help(cmd_env_t *env, int argc, char **argv)
{
    cmdtbl_t *p = (cmdtbl_t *)&cmdtbl[0];
    while (p->command != 0) {
        ntstdio_printf(CMD_NTSTDIO(env), "%s\t%s\n", p->command, p->description);
        p++;
    }
}

