/*
 *
 *    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
 *      Implementation of DeviceDescOptions object, which handles parsing of command line options
 *      that specify descriptive information about the simulated "device" used in test applications.
 *
 */


#include "ToolCommon.h"
#include <Weave/Support/CodeUtils.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/common/CommonProfile.h>
#include <Weave/Profiles/vendor/nestlabs/device-description/NestProductIdentifiers.hpp>
#include "DeviceDescOptions.h"

using namespace nl::Weave::Profiles::DeviceDescription;

DeviceDescOptions gDeviceDescOptions;

DeviceDescOptions::DeviceDescOptions()
{
    static OptionDef optionDefs[] =
    {
        { "serial-num",       kArgumentRequired, kToolCommonOpt_DeviceSerialNum        },
        { "vendor-id",        kArgumentRequired, kToolCommonOpt_DeviceVendorId         },
        { "product-id",       kArgumentRequired, kToolCommonOpt_DeviceProductId        },
        { "product-rev",      kArgumentRequired, kToolCommonOpt_DeviceProductRevision  },
        { "software-version", kArgumentRequired, kToolCommonOpt_DeviceSoftwareVersion  },
        { NULL }
    };
    OptionDefs = optionDefs;

    HelpGroupName = "DEVICE DESCRIPTION OPTIONS";

    OptionHelp =
        "  --serial-num <string>\n"
        "       Device serial number. Defaults to \"mock-device\".\n"
        "\n"
        "  --vendor-id <int>\n"
        "       Device vendor id.  Defaults to 0x235A (Nest Labs)\n"
        "\n"
        "  --product-id <int>\n"
        "       Device product id. Defaults to 5 (Nest Protect).\n"
        "\n"
        "  --product-rev <int>\n"
        "       Device product revision. Defaults to 1.\n"
        "\n"
        "  --software-version <string>\n"
        "       Device software version string. Defaults to \"mock-device/1.0\".\n"
        "\n";

    // Setup Defaults.
    BaseDeviceDesc.Clear();
    BaseDeviceDesc.VendorId = kWeaveVendor_NestLabs;
    BaseDeviceDesc.ProductId = nl::Weave::Profiles::Vendor::Nestlabs::DeviceDescription::kNestWeaveProduct_Topaz;
    BaseDeviceDesc.ProductRevision = 1;
    BaseDeviceDesc.ManufacturingDate.Year = 2013;
    BaseDeviceDesc.ManufacturingDate.Month = 1;
    BaseDeviceDesc.ManufacturingDate.Day = 1;
    memset(BaseDeviceDesc.Primary802154MACAddress, 0x11, sizeof(BaseDeviceDesc.Primary802154MACAddress));
    memset(BaseDeviceDesc.PrimaryWiFiMACAddress, 0x22, sizeof(BaseDeviceDesc.PrimaryWiFiMACAddress));
    strcpy(BaseDeviceDesc.RendezvousWiFiESSID, "MOCK-1111");
    strcpy(BaseDeviceDesc.SerialNumber, "mock-device");
    strcpy(BaseDeviceDesc.SoftwareVersion, "mock-device/1.0");
    BaseDeviceDesc.DeviceFeatures =
        WeaveDeviceDescriptor::kFeature_HomeAlarmLinkCapable |
        WeaveDeviceDescriptor::kFeature_LinePowered;
    // NOTE: For security reasons, pairing codes should only ever appear in device descriptors that are
    // encoded into QR codes. options.BaseDeviceDesc contains the device descriptor fields that get sent over the
    // network (e.g. in an IdentifyDevice exchange).  Therefore the PairingCode field should never be
    // set here.
}

void DeviceDescOptions::GetDeviceDesc(WeaveDeviceDescriptor& deviceDesc)
{
    deviceDesc = BaseDeviceDesc;
    deviceDesc.DeviceId = FabricState.LocalNodeId;
    deviceDesc.FabricId = FabricState.FabricId;
    memset(deviceDesc.PairingCode, 0, sizeof(deviceDesc.PairingCode));
}

bool DeviceDescOptions::HandleOption(const char *progName, OptionSet *optSet, int id, const char *name, const char *arg)
{
    DeviceDescOptions& options = *static_cast<DeviceDescOptions *>(optSet);

    switch (id)
    {
    case kToolCommonOpt_DeviceSerialNum:
        if (strlen(arg) > WeaveDeviceDescriptor::kMaxSerialNumberLength)
        {
            PrintArgError("%s: Invalid value specified for device serial number (value too long): %s\n", progName, arg);
            return false;
        }
        strncpy(options.BaseDeviceDesc.SerialNumber, arg, sizeof(options.BaseDeviceDesc.SerialNumber));
        break;
    case kToolCommonOpt_DeviceVendorId:
        if (!ParseInt(arg, options.BaseDeviceDesc.VendorId) || options.BaseDeviceDesc.VendorId == 0 || options.BaseDeviceDesc.VendorId >= 0xFFF0)
        {
            PrintArgError("%s: Invalid value specified for device vendor ID: %s\n", progName, arg);
            return false;
        }
        break;
    case kToolCommonOpt_DeviceProductId:
        if (!ParseInt(arg, options.BaseDeviceDesc.ProductId) || options.BaseDeviceDesc.ProductId == 0 || options.BaseDeviceDesc.ProductId == 0xFFFF)
        {
            PrintArgError("%s: Invalid value specified for device product ID: %s\n", progName, arg);
            return false;
        }
        break;
    case kToolCommonOpt_DeviceProductRevision:
        if (!ParseInt(arg, options.BaseDeviceDesc.ProductRevision))
        {
            PrintArgError("%s: Invalid value specified for device product revision: %s\n", progName, arg);
            return false;
        }
        break;
    case kToolCommonOpt_DeviceSoftwareVersion:
        if (strlen(arg) > WeaveDeviceDescriptor::kMaxSoftwareVersionLength)
        {
            PrintArgError("%s: Invalid value specified for device software version (value too long): %s\n", progName, arg);
            return false;
        }
        strncpy(options.BaseDeviceDesc.SoftwareVersion, arg, sizeof(options.BaseDeviceDesc.SoftwareVersion));
        break;
    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
        return false;
    }

    return true;
}
