/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file implements a command line tool, weave-heartbeat, for the
 *      Weave Heartbeat Profile.
 *
 */

#define __STDC_FORMAT_MACROS
#define __STDC_LIMIT_MACROS

#include <inttypes.h>
#include <limits.h>

#include "ToolCommon.h"
#include <Weave/WeaveVersion.h>
#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Core/WeaveSecurityMgr.h>
#include <Weave/Core/WeaveBinding.h>
#include <Weave/Profiles/time/WeaveTime.h>
#include <Weave/Profiles/heartbeat/WeaveHeartbeat.h>
#include <Weave/Profiles/security/WeaveSecurity.h>
#include <Weave/Profiles/service-directory/ServiceDirectory.h>

using nl::StatusReportStr;
using namespace nl::Weave::Profiles::Heartbeat;
using namespace nl::Weave::Profiles::Security;

#define TOOL_NAME "weave-heartbeat"

static bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg);
static bool HandleNonOptionArgs(const char *progName, int argc, char *argv[]);
static void HandleHeartbeatReceived(const WeaveMessageInfo *aMsgInfo, uint8_t nodeState, WEAVE_ERROR err);
static bool ParseDestAddress(const char *progName, const char *arg);
static void HeartbeatSenderEventHandler(void *appState, WeaveHeartbeatSender::EventType eventType, const WeaveHeartbeatSender::InEventParam& inParam, WeaveHeartbeatSender::OutEventParam& outParam);
static void BindingEventHandler(void *appState, Binding::EventType eventType, const Binding::InEventParam& inParam, Binding::OutEventParam& outParam);

bool Listening = false;
uint32_t MaxHeartbeatCount = UINT32_MAX;
uint32_t HeartbeatInterval = 1000; // 1 second
uint32_t HeartbeatWindow = 0;
bool Debug = false;
uint64_t DestNodeId;
const char *DestAddr = NULL;
IPAddress DestIPAddr;
uint16_t DestPort;
InterfaceId DestIntf = INET_NULL_INTERFACEID;
uint32_t HeartbeatCount = 0;
WeaveHeartbeatSender HeartbeatSender;
WeaveHeartbeatReceiver HeartbeatReceiver;
bool RequestAck = false;

static OptionDef gToolOptionDefs[] =
{
    { "listen",       kNoArgument,       'L' },
    { "dest-addr",    kArgumentRequired, 'D' },
    { "count",        kArgumentRequired, 'c' },
    { "interval",     kArgumentRequired, 'i' },
    { "window",       kArgumentRequired, 'W' },
    { "request-ack",  kNoArgument,       'r' },
    { }
};

static const char *const gToolOptionHelp =
    "  -D, --dest-addr <host>[:<port>][%<interface>]\n"
    "       Send Heartbeats to a specific address rather than one\n"
    "       derived from the destination node id. <host> can be a hostname,\n"
    "       an IPv4 address or an IPv6 address. If <port> is specified, Heartbeat\n"
    "       requests will be sent to the specified port. If <interface> is\n"
    "       specified, Heartbeats will be sent over the specified local\n"
    "       interface.\n"
    "\n"
    "       NOTE: When specifying a port with an IPv6 address, the IPv6 address\n"
    "       must be enclosed in brackets, e.g. [fd00:0:1:1::1]:11095.\n"
    "\n"
    "  -c, --count <num>\n"
    "       Send the specified number of Heartbeats and exit.\n"
    "\n"
    "  -i, --interval <ms>\n"
    "       Send Heartbeats at the specified interval in milliseconds.\n"
    "\n"
    "  -W, --window <ms>\n"
    "       Randomize the sending of Heartbeats over the specified interval in milliseconds.\n"
    "\n"
    "  -L, --listen\n"
    "       Listen and respond to Heartbeats sent from another node.\n"
    "\n"
    "  -r, --request-ack\n"
    "       Use Weave Reliable Messaging when sending heartbeats over UDP.\n"
    "\n";

static OptionSet gToolOptions =
{
    HandleOption,
    gToolOptionDefs,
    "GENERAL OPTIONS",
    gToolOptionHelp
};

static HelpOptions gHelpOptions(
    TOOL_NAME,
    "Usage: " TOOL_NAME " [<options...>] <dest-node-id>[@<dest-host>[:<dest-port>][%%<interface>]]\n"
    "       " TOOL_NAME " [<options...>] --listen\n",
    WEAVE_VERSION_STRING "\n" WEAVE_TOOL_COPYRIGHT
);

static OptionSet *gToolOptionSets[] =
{
    &gToolOptions,
    &gNetworkOptions,
    &gWeaveNodeOptions,
    &gWRMPOptions,
    &gFaultInjectionOptions,
    &gHelpOptions,
    NULL
};

int main(int argc, char *argv[])
{
    WEAVE_ERROR err;

    InitToolCommon();

    SetSIGUSR1Handler();

    // Use a smaller default WRMP retransmission interval and count so that the total retry time
    // does not exceed the default heartbeat interval of 1 second.
    gWRMPOptions.RetransInterval = 200;
    gWRMPOptions.RetransCount = 2;

    if (argc == 1)
    {
        gHelpOptions.PrintBriefUsage(stderr);
        exit(EXIT_FAILURE);
    }

    if (!ParseArgsFromEnvVar(TOOL_NAME, TOOL_OPTIONS_ENV_VAR_NAME, gToolOptionSets, NULL, true) ||
        !ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets, HandleNonOptionArgs) ||
        !ResolveWeaveNetworkOptions(TOOL_NAME, gWeaveNodeOptions, gNetworkOptions))
    {
        exit(EXIT_FAILURE);
    }

    InitSystemLayer();

    InitNetwork();

    InitWeaveStack(true, true);

    if (!Listening) // heartbeat sender
    {
        // Create a binding for the HeartbeatSender.
        Binding *binding = ExchangeMgr.NewBinding(BindingEventHandler, NULL);

        // Initialize the HeartbeatSender object.
        err = HeartbeatSender.Init(&ExchangeMgr, binding, HeartbeatSenderEventHandler, NULL);
        if (err != WEAVE_NO_ERROR)
        {
            printf("WeaveHeartbeatSender.Init failed: %s\n", ErrorStr(err));
            exit(EXIT_FAILURE);
        }

        // Release the binding (the HeartbeatSender will retain its own reference).
        binding->Release();
    }
    else // heartbeat receiver
    {
        // Initialize the HeartbeatReceiver application.
        err = HeartbeatReceiver.Init(&ExchangeMgr);
        if (err)
        {
            printf("WeaveHeartbeatReceiver.Init failed: %s\n", ErrorStr(err));
            exit(EXIT_FAILURE);
        }

        // Arrange to get a callback whenever a Heartbeat is received.
        HeartbeatReceiver.OnHeartbeatReceived = HandleHeartbeatReceived;
    }

    PrintNodeConfig();

    if (!Listening) // heartbeat sender
    {
        printf("Sending");
        if (MaxHeartbeatCount != UINT32_MAX)
            printf(" %u", MaxHeartbeatCount);
        printf(" Heartbeats via %s to node %" PRIX64, (RequestAck) ? "UDP with WRMP" : "UDP", DestNodeId);
        if (DestAddr != NULL)
            printf(" (%s)", DestAddr);
        printf(" every %" PRId32 " ms", HeartbeatInterval);
        if (HeartbeatWindow > 0)
            printf(", with a randomization window of %" PRId32 " ms", HeartbeatWindow);
        printf("\n");

        HeartbeatSender.SetConfiguration(HeartbeatInterval, 0, HeartbeatWindow);
        HeartbeatSender.SetRequestAck(RequestAck);
        HeartbeatSender.SetSubscriptionState(0x01);

        err = HeartbeatSender.StartHeartbeat();
        if (err != WEAVE_NO_ERROR)
        {
            printf("HeartbeatSender.StartHeartbeat failed: %s\n", ErrorStr(err));
            exit(EXIT_FAILURE);
        }
    }
    else // heartbeat receiver
    {
        printf("Listening for Heartbeats...\n");
    }

    while (!Done)
    {
        struct timeval sleepTime;
        sleepTime.tv_sec = 0;
        sleepTime.tv_usec = 100000;

        ServiceNetwork(sleepTime);

        if (MaxHeartbeatCount != UINT32_MAX && HeartbeatCount >= MaxHeartbeatCount)
            Done = true;
    }

    HeartbeatSender.Shutdown();
    HeartbeatReceiver.Shutdown();

    ShutdownWeaveStack();
    ShutdownNetwork();
    ShutdownSystemLayer();

    return EXIT_SUCCESS;
}

bool HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
{
    switch (id)
    {
    case 'L':
        Listening = true;
        break;
    case 'c':
        if (!ParseInt(arg, MaxHeartbeatCount))
        {
            PrintArgError("%s: Invalid value specified for send count: %s\n", progName, arg);
            return false;
        }
        break;
    case 'i':
        if (!ParseInt(arg, HeartbeatInterval))
        {
            PrintArgError("%s: Invalid value specified for heartbeat interval: %s\n", progName, arg);
            return false;
        }
        break;
    case 'W':
        if (!ParseInt(arg, HeartbeatWindow))
        {
            PrintArgError("%s: Invalid value specified for heartbeat randomization window: %s\n", progName, arg);
            return false;
        }
        break;
    case 'D':
        return ParseDestAddress(progName, arg);
        break;
    case 'r':
#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
        RequestAck = true;
        break;
#else
        PrintArgError("%s: WRMP not supported: %s\n", progName, name);
        return false;
#endif
    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
        return false;
    }

    return true;
}

bool HandleNonOptionArgs(const char *progName, int argc, char *argv[])
{
    const char *destAddr = NULL;

    if (argc > 0)
    {
        if (argc > 1)
        {
            PrintArgError("%s: Unexpected argument: %s\n", progName, argv[1]);
            return false;
        }

        if (Listening)
        {
            PrintArgError("%s: Please specify either a node id or --listen\n", progName);
            return false;
        }

        const char *nodeId = argv[0];
        char *p = (char *)strchr(nodeId, '@');
        if (p != NULL)
        {
            *p = 0;
            destAddr = p+1;
        }

        if (!ParseNodeId(nodeId, DestNodeId))
        {
            PrintArgError("%s: Invalid value specified for destination node-id: %s\n", progName, nodeId);
            return false;
        }

        if (destAddr != NULL && !ParseDestAddress(progName, destAddr))
            return false;
    }

    else
    {
        if (!Listening)
        {
            PrintArgError("%s: Please specify either a node id or --listen\n", progName);
            return false;
        }
    }

    return true;
}

void HandleHeartbeatSent(uint64_t destId, IPAddress destAddr, uint8_t state, WEAVE_ERROR err)
{
    char ipAddrStr[64];
    destAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    printf("Heartbeat sent to node %" PRIX64 " (%s): state=%u, err=%s\n", destId, ipAddrStr, state, ErrorStr(err));

    HeartbeatCount++;
}

void HandleHeartbeatReceived(const WeaveMessageInfo *aMsgInfo, uint8_t nodeState, WEAVE_ERROR err)
{
    char ipAddrStr[64];
    aMsgInfo->InPacketInfo->SrcAddress.ToString(ipAddrStr, sizeof(ipAddrStr));

    printf("Heartbeat from node %" PRIX64 " (%s): state=%u, err=%s\n", aMsgInfo->SourceNodeId, ipAddrStr, nodeState, ErrorStr(err));

    HeartbeatCount++;
}

bool ParseDestAddress(const char *progName, const char *arg)
{
    WEAVE_ERROR err;
    const char *addr;
    uint16_t addrLen;
    const char *intfName;
    uint16_t intfNameLen;

    err = ParseHostPortAndInterface(arg, strlen(arg), addr, addrLen, DestPort, intfName, intfNameLen);
    if (err != INET_NO_ERROR)
    {
        PrintArgError("%s: Invalid destination address: %s\n", progName, arg);
        return false;
    }

    if (!IPAddress::FromString(addr, DestIPAddr))
    {
        PrintArgError("%s: Invalid destination address: %s\n", progName, arg);
        return false;
    }

    if (intfName != NULL)
    {
        err = InterfaceNameToId(intfName, DestIntf);
        if (err != INET_NO_ERROR)
        {
            PrintArgError("%s: Invalid interface name: %s\n", progName, intfName);
            return false;
        }
    }

    DestAddr = arg;

    return true;
}

void HeartbeatSenderEventHandler(void *appState, WeaveHeartbeatSender::EventType eventType, const WeaveHeartbeatSender::InEventParam& inParam, WeaveHeartbeatSender::OutEventParam& outParam)
{
    WeaveHeartbeatSender *sender = inParam.Source;
    Binding *binding = sender->GetBinding();

    switch (eventType)
    {
    case WeaveHeartbeatSender::kEvent_HeartbeatSent:
        printf("Heartbeat sent to node %" PRIX64 ": state=%u\n",
               binding->GetPeerNodeId(), sender->GetSubscriptionState());
        HeartbeatCount++;
        break;
    case WeaveHeartbeatSender::kEvent_HeartbeatFailed:
        printf("Heartbeat FAILED to node %" PRIX64 ": state=%u, err=%s\n",
               binding->GetPeerNodeId(), sender->GetSubscriptionState(),
               ErrorStr(inParam.HeartbeatFailed.Reason));
        HeartbeatCount++;
        break;
    default:
        WeaveHeartbeatSender::DefaultEventHandler(appState, eventType, inParam, outParam);
        break;
    }
}

void BindingEventHandler(void *appState, Binding::EventType eventType, const Binding::InEventParam& inParam, Binding::OutEventParam& outParam)
{
    switch (eventType)
    {
    case Binding::kEvent_PrepareRequested:
    {
        Binding::Configuration bindingConfig = inParam.Source->BeginConfiguration()
            .Target_NodeId(DestNodeId)
            .Transport_UDP()
            .Transport_DefaultWRMPConfig(gWRMPOptions.GetWRMPConfig())
            .Security_None();
        if (DestAddr != NULL)
        {
            bindingConfig.TargetAddress_IP(DestIPAddr, DestPort, DestIntf);
        }
        outParam.PrepareRequested.PrepareError = bindingConfig.PrepareBinding();
        break;
    }
    default:
        Binding::DefaultEventHandler(appState, eventType, inParam, outParam);
        break;
    }
}
