/**
 * The function is responsible for discovery of owned device is current subnet. It will list
 * all the device in subnet which are owned by calling provisioning client.
 *
 * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
 *                    server before returning the list of devices.
 * @param[out] ppList List of device owned by provisioning tool.
 * @return OTM_SUCCESS in case of success and other value otherwise.
 */
OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
{
    if( ppList == NULL || *ppList != NULL || 0 == timeout)
    {
        return OC_STACK_INVALID_PARAM;
    }

    return PMDeviceDiscovery(timeout, true, ppList);
}
/*
* Function to device revocation
* This function will remove credential of target device from all devices in subnet.
*
* @param[in] ctx Application context would be returned in result callback
* @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
* @param[in] pTargetDev Device information to be revoked.
* @param[in] resultCallback callback provided by API user, callback will be called when
*            credential revocation is finished.
 * @return  OC_STACK_OK in case of success and other value otherwise.
*/
OCStackResult OCRemoveDeviceWithUuid(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
                            const OicUuid_t* pTargetUuid,
                            OCProvisionResultCB resultCallback)
{
    OIC_LOG(INFO, TAG, "IN OCRemoveDeviceWithUuid");
    OCStackResult res = OC_STACK_ERROR;
    if (!pTargetUuid || 0 == waitTimeForOwnedDeviceDiscovery)
    {
        OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : Invalied parameters");
        return OC_STACK_INVALID_PARAM;
    }
    if (!resultCallback)
    {
        OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : NULL Callback");
        return OC_STACK_INVALID_CALLBACK;
    }

    OCProvisionDev_t* pOwnedDevList = NULL;
    //2. Find owned device from the network
    res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
    if (OC_STACK_OK != res)
    {
        OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to PMDeviceDiscovery");
        goto error;
    }

    OCProvisionDev_t* pTargetDev = NULL;
    LL_FOREACH(pOwnedDevList, pTargetDev)
    {
        if(memcmp(&pTargetDev->doxm->deviceID.id, pTargetUuid->id, sizeof(pTargetUuid->id)) == 0)
        {
            break;
        }
    }

    char* strUuid = NULL;
    if(OC_STACK_OK != ConvertUuidToStr(pTargetUuid, &strUuid))
    {
        OIC_LOG(WARNING, TAG, "Failed to covert UUID to String.");
        goto error;
    }

    if(pTargetDev)
    {
        OIC_LOG_V(INFO, TAG, "[%s] is dectected on the network.", strUuid);
        OIC_LOG_V(INFO, TAG, "Trying [%s] revocation.", strUuid);

        // Send DELETE requests to linked devices
        OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
        resReq = SRPRemoveDeviceWithoutDiscovery(ctx, pOwnedDevList, pTargetDev, resultCallback);
        if (OC_STACK_OK != resReq)
        {
            if (OC_STACK_CONTINUE == resReq)
            {
                OIC_LOG(DEBUG, TAG, "OCRemoveDeviceWithUuid : Revoked device has no linked device except PT.");
            }
            else
            {
                OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to invoke SRPRemoveDevice");
                res = resReq;
                OICFree(strUuid);
                goto error;
            }
        }

        res = RemoveDeviceInfoFromLocal(pTargetDev);
        if(OC_STACK_OK != res)
        {
            OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Filed to remove the device information from local.");
            OICFree(strUuid);
            goto error;
        }

        if(OC_STACK_CONTINUE == resReq)
        {
            /**
              * If there is no linked device, PM does not send any request.
              * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
              */
            if(resultCallback)
            {
                resultCallback(ctx, 0, NULL, false);
            }
            res = OC_STACK_OK;
        }
    }
    else
    {
        OIC_LOG_V(WARNING, TAG, "OCRemoveDeviceWithUuid : Failed to find the [%s] on the network.", strUuid);
        res = OC_STACK_ERROR;
    }

error:
    OICFree(strUuid);
    PMDeleteDeviceList(pOwnedDevList);
    OIC_LOG(INFO, TAG, "OUT OCRemoveDeviceWithUuid");
    return res;
}