/*
 *
 *    Copyright (c) 2018 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.
 */

#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/internal/ServiceProvisioningServer.h>
#include <Weave/Profiles/common/CommonProfile.h>

using namespace ::nl;
using namespace ::nl::Weave;
using namespace ::nl::Weave::Profiles;
using namespace ::nl::Weave::Profiles::ServiceProvisioning;

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

ServiceProvisioningServer ServiceProvisioningServer::sInstance;

WEAVE_ERROR ServiceProvisioningServer::Init(void)
{
    WEAVE_ERROR err;

    // Call init on the server base class.
    err = ServerBaseClass::Init(&::nl::Weave::DeviceLayer::ExchangeMgr);
    SuccessOrExit(err);

    // Set the pointer to the delegate object.
    SetDelegate(this);

    mProvServiceBinding = NULL;
    mWaitingForServiceConnectivity = false;

exit:
    return err;
}

WEAVE_ERROR ServiceProvisioningServer::HandleRegisterServicePairAccount(RegisterServicePairAccountMessage & msg)
{
    WEAVE_ERROR err;
    uint64_t curServiceId;

    // Check if a service is already provisioned. If so respond with "Too Many Services".
    err = ConfigurationMgr().GetServiceId(curServiceId);
    if (err == WEAVE_NO_ERROR)
    {
        err = sInstance.SendStatusReport(kWeaveProfile_ServiceProvisioning,
                (curServiceId == msg.ServiceId) ? kStatusCode_ServiceAlreadyRegistered : kStatusCode_TooManyServices);
        ExitNow();
    }
    if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND)
    {
        err = WEAVE_NO_ERROR;
    }
    SuccessOrExit(err);

    // Validate the service config. We don't want to get any further along before making sure the data is good.
    if (!ServiceProvisioningServer::IsValidServiceConfig(msg.ServiceConfig, msg.ServiceConfigLen))
    {
        err = sInstance.SendStatusReport(kWeaveProfile_ServiceProvisioning, kStatusCode_InvalidServiceConfig);
        ExitNow();
    }

    WeaveLogProgress(DeviceLayer, "Registering new service: %" PRIx64 " (account id %.*s)", msg.ServiceId, (int)msg.AccountIdLen, msg.AccountId);

    // Store the service id and the service config in persistent storage.
    err = ConfigurationMgr().StoreServiceProvisioningData(msg.ServiceId, msg.ServiceConfig, msg.ServiceConfigLen, NULL, 0);
    SuccessOrExit(err);

    // Post an event alerting other subsystems to the change in the service provisioning state.
    {
        WeaveDeviceEvent event;
        event.Type = DeviceEventType::kServiceProvisioningChange;
        event.ServiceProvisioningChange.IsServiceProvisioned = true;
        event.ServiceProvisioningChange.ServiceConfigUpdated = false;
        PlatformMgr().PostEvent(&event);
    }

#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

    // Initiate the process of sending a PairDeviceToAccount request to the Service Provisioning service.
    PlatformMgr().ScheduleWork(AsyncStartPairDeviceToAccount);

#else // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

    // Store the account id in persistent storage.
    err = ConfigurationMgr().StorePairedAccountId(msg.AccountId, msg.AccountIdLen);
    SuccessOrExit(err);

    // Post an event alerting other subsystems that the device is now paired to an account.
    {
        WeaveDeviceEvent event;
        event.Type = DeviceEventType::kAccountPairingChange;
        event.AccountPairingChange.IsPairedToAccount = true;
        PlatformMgr().PostEvent(&event);
    }

    // Send a success StatusReport for the RegisterServicePairDevice request.
    SendSuccessResponse();

#endif // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

exit:
    return err;
}

WEAVE_ERROR ServiceProvisioningServer::HandleUpdateService(UpdateServiceMessage& msg)
{
    WEAVE_ERROR err;
    uint64_t curServiceId;

    // Verify that the service id matches the existing service.  If not respond with "No Such Service".
    err = ConfigurationMgr().GetServiceId(curServiceId);
    if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND || curServiceId != msg.ServiceId)
    {
        err = sInstance.SendStatusReport(kWeaveProfile_ServiceProvisioning, kStatusCode_NoSuchService);
        ExitNow();
    }
    SuccessOrExit(err);

    // Validate the service config. We don't want to get any further along before making sure the data is good.
    if (!ServiceProvisioningServer::IsValidServiceConfig(msg.ServiceConfig, msg.ServiceConfigLen))
    {
        err = sInstance.SendStatusReport(kWeaveProfile_ServiceProvisioning, kStatusCode_InvalidServiceConfig);
        ExitNow();
    }

    // Save the new service configuration in device persistent storage, replacing the existing value.
    err = ConfigurationMgr().StoreServiceConfig(msg.ServiceConfig, msg.ServiceConfigLen);
    SuccessOrExit(err);

    // Post an event alerting other subsystems that the service config has changed.
    {
        WeaveDeviceEvent event;
        event.Type = DeviceEventType::kServiceProvisioningChange;
        event.ServiceProvisioningChange.IsServiceProvisioned = true;
        event.ServiceProvisioningChange.ServiceConfigUpdated = true;
        PlatformMgr().PostEvent(&event);
    }

    // Send "Success" back to the requestor.
    err = sInstance.SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR ServiceProvisioningServer::HandleUnregisterService(uint64_t serviceId)
{
    WEAVE_ERROR err;
    uint64_t curServiceId;

    // Verify that the service id matches the existing service.  If not respond with "No Such Service".
    err = ConfigurationMgr().GetServiceId(curServiceId);
    if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND || curServiceId != serviceId)
    {
        err = sInstance.SendStatusReport(kWeaveProfile_ServiceProvisioning, kStatusCode_NoSuchService);
        ExitNow();
    }
    SuccessOrExit(err);

    // Clear the persisted service provisioning data, if present.
    err = ConfigurationMgr().ClearServiceProvisioningData();
    SuccessOrExit(err);

    // Send "Success" back to the requestor.
    err = sInstance.SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

bool ServiceProvisioningServer::IsPairedToAccount(void) const
{
    return ConfigurationMgr().IsServiceProvisioned() && ConfigurationMgr().IsPairedToAccount();
}

void ServiceProvisioningServer::OnPlatformEvent(const WeaveDeviceEvent * event)
{
#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

    // If a tunnel to the service has been established...
    // OR if service connectivity has been established (e.g. via Thread)...
    if ((event->Type == DeviceEventType::kServiceTunnelStateChange &&
         event->ServiceTunnelStateChange.Result == kConnectivity_Established) ||
        (event->Type == DeviceEventType::kServiceConnectivityChange &&
         event->ServiceConnectivityChange.Overall.Result == kConnectivity_Established))
    {
        // If a RegisterServicePairAccount request is pending and the system is waiting for
        // the service connectivity to be established, initiate the PairDeviceToAccount request now.
        if (mCurClientOp != NULL && mWaitingForServiceConnectivity)
        {
            StartPairDeviceToAccount();
        }
    }

#endif // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING
}

#if !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

void ServiceProvisioningServer::StartPairDeviceToAccount(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    // If the system does not currently have a tunnel established with the service,
    // AND the system does not have service connectivity by some other means (e.g. Thread)
    // wait a period of time for connectivity to be established.
    if (!ConnectivityMgr().HaveServiceConnectivity() && !ConnectivityMgr().IsServiceTunnelConnected())
    {
        mWaitingForServiceConnectivity = true;

        err = SystemLayer.StartTimer(WEAVE_DEVICE_CONFIG_SERVICE_PROVISIONING_CONNECTIVITY_TIMEOUT,
                HandleServiceConnectivityTimeout,
                NULL);
        SuccessOrExit(err);
        ExitNow();

        WeaveLogProgress(DeviceLayer, "Waiting for service connectivity to complete RegisterServicePairDevice action");
    }

    mWaitingForServiceConnectivity = false;
    SystemLayer.CancelTimer(HandleServiceConnectivityTimeout, NULL);

    WeaveLogProgress(DeviceLayer, "Initiating communication with Service Provisioning service");

    // Create a binding and begin the process of preparing it for talking to the Service Provisioning
    // service. When this completes HandleProvServiceBindingEvent will be called with a BindingReady event.
    mProvServiceBinding = ExchangeMgr->NewBinding(HandleProvServiceBindingEvent, NULL);
    VerifyOrExit(mProvServiceBinding != NULL, err = WEAVE_ERROR_NO_MEMORY);
    err = mProvServiceBinding->BeginConfiguration()
            .Target_ServiceEndpoint(WEAVE_DEVICE_CONFIG_SERVICE_PROVISIONING_ENDPOINT_ID)
            .Transport_UDP_WRM()
            .Exchange_ResponseTimeoutMsec(WEAVE_DEVICE_CONFIG_SERVICE_PROVISIONING_REQUEST_TIMEOUT)
            .Security_SharedCASESession()
            .PrepareBinding();
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        HandlePairDeviceToAccountResult(err, kWeaveProfile_Common, Profiles::Common::kStatus_InternalServerProblem);
    }
}

void ServiceProvisioningServer::SendPairDeviceToAccountRequest(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    const RegisterServicePairAccountMessage & regServiceMsg = mCurClientOpMsg.RegisterServicePairAccount;
    uint8_t devDesc[Profiles::DeviceDescription::WeaveDeviceDescriptor::kMaxEncodedTLVLength]; // TODO: make configurable
    size_t devDescLen;

    // Generate a device descriptor for the local device in TLV.
    err = ConfigurationMgr().GetDeviceDescriptorTLV(devDesc, sizeof(devDesc), devDescLen);
    SuccessOrExit(err);

    // Call up to a helper function the server base class to encode and send a PairDeviceToAccount request to
    // the Service Provisioning service.  This will ultimately result in a call to HandlePairDeviceToAccountResult
    // with the result.
    //
    // Pass through the values for Service Id, Account Id, Pairing Token and Pairing Init Data that
    // were received in the Register Service message.  For Device Init Data, pass the encoded device
    // descriptor.  Finally, pass the id of the Weave fabric for which the device is a member.
    //
    WeaveLogProgress(DeviceLayer, "Sending PairDeviceToAccount request to Service Provisioning service");
    err = ServerBaseClass::SendPairDeviceToAccountRequest(mProvServiceBinding,
            regServiceMsg.ServiceId, FabricState->FabricId,
            regServiceMsg.AccountId, regServiceMsg.AccountIdLen,
            regServiceMsg.PairingToken, regServiceMsg.PairingTokenLen,
            regServiceMsg.PairingInitData, regServiceMsg.PairingInitDataLen,
            devDesc, devDescLen);
    SuccessOrExit(err);

exit:
    if (err != WEAVE_NO_ERROR)
    {
        HandlePairDeviceToAccountResult(err, kWeaveProfile_Common, Profiles::Common::kStatus_InternalServerProblem);
    }
}

void ServiceProvisioningServer::HandlePairDeviceToAccountResult(WEAVE_ERROR err, uint32_t statusReportProfileId, uint16_t statusReportStatusCode)
{
    // Close the binding if necessary.
    if (mProvServiceBinding != NULL)
    {
        mProvServiceBinding->Close();
        mProvServiceBinding = NULL;
    }

    // Return immediately if for some reason the client's RegisterServicePairAccount request
    // is no longer pending.  Note that, even if the PairDeviceToAccount request succeeded,
    // the device must clear the persisted service configuration in this case because it has
    // lost access to the account id (which was in the RegisterServicePairAccount message)
    // and therefore cannot complete the process of registering the service.
    if (mCurClientOp == NULL)
    {
        ExitNow(err = WEAVE_ERROR_INCORRECT_STATE);
    }

    // If the PairDeviceToAccount request was successful...
    if (err == WEAVE_NO_ERROR)
    {
        const RegisterServicePairAccountMessage & regServiceMsg = mCurClientOpMsg.RegisterServicePairAccount;

        // Store the account id in persistent storage.  This is the final step of registering a
        // service and marks that the device is properly associated with a user's account.
        err = ConfigurationMgr().StorePairedAccountId(regServiceMsg.AccountId, regServiceMsg.AccountIdLen);
        SuccessOrExit(err);

        // Post an event alerting other subsystems that the device is now paired to an account.
        {
            WeaveDeviceEvent event;
            event.Type = DeviceEventType::kAccountPairingChange;
            event.AccountPairingChange.IsPairedToAccount = true;
            PlatformMgr().PostEvent(&event);
        }

        WeaveLogProgress(DeviceLayer, "PairDeviceToAccount request completed successfully");

        // Send a success StatusReport back to the client.
        err = SendSuccessResponse();
        SuccessOrExit(err);
    }

exit:

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceLayer, "PairDeviceToAccount request failed with %s: %s",
                 (err == WEAVE_ERROR_STATUS_REPORT_RECEIVED) ? "status report from service" : "local error",
                 (err == WEAVE_ERROR_STATUS_REPORT_RECEIVED)
                  ? ::nl::StatusReportStr(statusReportProfileId, statusReportStatusCode)
                  : ::nl::ErrorStr(err));

        // Since we're failing the RegisterServicePairDevice request, clear the persisted service configuration.
        ConfigurationMgr().ClearServiceProvisioningData();

        // Choose an appropriate StatusReport to return if not already given.
        if (statusReportProfileId == 0 && statusReportStatusCode == 0)
        {
            if (err == WEAVE_ERROR_TIMEOUT)
            {
                statusReportProfileId = kWeaveProfile_ServiceProvisioning;
                statusReportStatusCode = Profiles::ServiceProvisioning::kStatusCode_ServiceCommunicationError;
            }
            else
            {
                statusReportProfileId = kWeaveProfile_Common;
                statusReportStatusCode = Profiles::Common::kStatus_InternalServerProblem;
            }
        }

        // Send an error StatusReport back to the client.  Only include the local error code if it isn't
        // WEAVE_ERROR_STATUS_REPORT_RECEIVED.
        SendStatusReport(statusReportProfileId, statusReportStatusCode,
                (err != WEAVE_ERROR_STATUS_REPORT_RECEIVED) ? err : WEAVE_NO_ERROR);
    }
}

void ServiceProvisioningServer::AsyncStartPairDeviceToAccount(intptr_t arg)
{
    sInstance.StartPairDeviceToAccount();
}

void ServiceProvisioningServer::HandleServiceConnectivityTimeout(System::Layer * /* unused */, void * /* unused */, System::Error /* unused */)
{
    sInstance.HandlePairDeviceToAccountResult(WEAVE_ERROR_TIMEOUT, 0, 0);
}

void ServiceProvisioningServer::HandleProvServiceBindingEvent(void * appState, Binding::EventType eventType,
            const Binding::InEventParam & inParam, Binding::OutEventParam & outParam)
{
    uint32_t statusReportProfileId;
    uint16_t statusReportStatusCode;

    switch (eventType)
    {
    case Binding::kEvent_BindingReady:
        sInstance.SendPairDeviceToAccountRequest();
        break;
    case Binding::kEvent_PrepareFailed:
        if (inParam.PrepareFailed.StatusReport != NULL)
        {
            statusReportProfileId = inParam.PrepareFailed.StatusReport->mProfileId;
            statusReportStatusCode = inParam.PrepareFailed.StatusReport->mStatusCode;
        }
        else
        {
            statusReportProfileId = kWeaveProfile_ServiceProvisioning;
            statusReportStatusCode = Profiles::ServiceProvisioning::kStatusCode_ServiceCommunicationError;
        }
        sInstance.HandlePairDeviceToAccountResult(inParam.PrepareFailed.Reason,
                statusReportProfileId, statusReportStatusCode);
        break;
    default:
        Binding::DefaultEventHandler(appState, eventType, inParam, outParam);
        break;
    }
}

#else // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

void ServiceProvisioningServer::HandlePairDeviceToAccountResult(WEAVE_ERROR err, uint32_t statusReportProfileId, uint16_t statusReportStatusCode)
{
}

#endif // !WEAVE_DEVICE_CONFIG_DISABLE_ACCOUNT_PAIRING

#if WEAVE_CONFIG_ENABLE_IFJ_SERVICE_FABRIC_JOIN
void ServiceProvisioningServer::HandleIFJServiceFabricJoinResult(WEAVE_ERROR err, uint32_t statusReportProfileId, uint16_t statusReportStatusCode)
{
}
#endif // WEAVE_CONFIG_ENABLE_IFJ_SERVICE_FABRIC_JOIN

} // namespace Internal
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl
