<commit_before>﻿using IotivityDotNet.Interop;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace IotivityDotNet
{
    public class ResourceClient : IDisposable
    {
        private IntPtr _handle;
        private OCCallbackData _observeCallbackData;
        private OCClientResponseHandler _observeCallbackHandler;
        private string _resourceUri;
        private DeviceAddress _address;

        public ResourceClient(DeviceAddress address, string resourceUri)
        {
            _observeCallbackData = new OCCallbackData();
            _observeCallbackData.cb = _observeCallbackHandler = OnObserveCallback;
            _resourceUri = resourceUri;
            _address = address;
            var result = OCStack.OCDoResource(out _handle, OCMethod.OC_REST_OBSERVE, resourceUri, address.OCDevAddr, IntPtr.Zero, OCConnectivityType.CT_DEFAULT, OCQualityOfService.OC_LOW_QOS, _observeCallbackData, null, 0);
            OCStackException.ThrowIfError(result, "Failed to observe resource");
        }

        ~ResourceClient()
        {
            OCStack.OCDeleteResource(_handle);
        }

        public Task<ClientResponse<RepPayload>> PostAsync(string resourceTypeName, Dictionary<string, object> data)
        {
            return SendAsync(resourceTypeName, data, OCMethod.OC_REST_POST);
        }

        public Task<ClientResponse<RepPayload>> PutAsync(string resourceTypeName, Dictionary<string, object> data)
        {
            return SendAsync(resourceTypeName, data, OCMethod.OC_REST_PUT);
        }

        public Task<ClientResponse<RepPayload>> GetAsync(string resourceTypeName)
        {
            return SendAsync(resourceTypeName, null, OCMethod.OC_REST_GET);
        }

        private async Task<ClientResponse<RepPayload>> SendAsync(string resourceTypeName, Dictionary<string, object> data, OCMethod method)
        {
            var tcs = new TaskCompletionSource<ClientResponse<RepPayload>>();
            var callbackData = new OCCallbackData();
            OCClientResponseHandler handler = (context, handle, clientResponse) =>
            {
                GCHandle.FromIntPtr(context).Free();
                if (clientResponse.result > OCStackResult.OC_STACK_RESOURCE_CHANGED)
                {
                    tcs.SetException(new Exception("Resource returned error: " + clientResponse.result.ToString()));
                }
                else
                {
                    tcs.SetResult(new ClientResponse<RepPayload>(clientResponse));
                }
                return OCStackApplicationResult.OC_STACK_DELETE_TRANSACTION;
            };
            var gcHandle = GCHandle.Alloc(handler);
            callbackData.cb = handler;
            callbackData.context = GCHandle.ToIntPtr(gcHandle);
            
            IntPtr payloadHandle = IntPtr.Zero;
            if (data != null)
            {
                RepPayload payload = new RepPayload();

                payload.SetUri(_resourceUri);
                payload.PopulateFromDictionary(data);
                payload.AddResourceType(resourceTypeName);
                payloadHandle = payload.Handle;
            }

            var result = OCStack.OCDoResource(out _handle, method, _resourceUri, _address.OCDevAddr, payloadHandle, OCConnectivityType.CT_DEFAULT, OCQualityOfService.OC_LOW_QOS, callbackData, null, 0);
            OCStackException.ThrowIfError(result, "Failed to send to resource");
            var response = await tcs.Task.ConfigureAwait(false);
            <commit_msg>Bug fix in sending resource type<commit_after>﻿using IotivityDotNet.Interop;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

namespace IotivityDotNet
{
    public class ResourceClient : IDisposable
    {
        private IntPtr _handle;
        private OCCallbackData _observeCallbackData;
        private OCClientResponseHandler _observeCallbackHandler;
        private string _resourceUri;
        private DeviceAddress _address;

        public ResourceClient(DeviceAddress address, string resourceUri)
        {
            _observeCallbackData = new OCCallbackData();
            _observeCallbackData.cb = _observeCallbackHandler = OnObserveCallback;
            _resourceUri = resourceUri;
            _address = address;
            var result = OCStack.OCDoResource(out _handle, OCMethod.OC_REST_OBSERVE, resourceUri, address.OCDevAddr, IntPtr.Zero, OCConnectivityType.CT_DEFAULT, OCQualityOfService.OC_LOW_QOS, _observeCallbackData, null, 0);
            OCStackException.ThrowIfError(result, "Failed to observe resource");
        }

        ~ResourceClient()
        {
            OCStack.OCDeleteResource(_handle);
        }

        public Task<ClientResponse<RepPayload>> PostAsync(string resourceTypeName, Dictionary<string, object> data)
        {
            return SendAsync(resourceTypeName, data, OCMethod.OC_REST_POST);
        }

        public Task<ClientResponse<RepPayload>> PutAsync(string resourceTypeName, Dictionary<string, object> data)
        {
            return SendAsync(resourceTypeName, data, OCMethod.OC_REST_PUT);
        }

        public Task<ClientResponse<RepPayload>> GetAsync(string resourceTypeName)
        {
            return SendAsync(resourceTypeName, null, OCMethod.OC_REST_GET);
        }

        private async Task<ClientResponse<RepPayload>> SendAsync(string resourceTypeName, Dictionary<string, object> data, OCMethod method)
        {
            var tcs = new TaskCompletionSource<ClientResponse<RepPayload>>();
            var callbackData = new OCCallbackData();
            OCClientResponseHandler handler = (context, handle, clientResponse) =>
            {
                GCHandle.FromIntPtr(context).Free();
                if (clientResponse.result > OCStackResult.OC_STACK_RESOURCE_CHANGED)
                {
                    tcs.SetException(new Exception("Resource returned error: " + clientResponse.result.ToString()));
                }
                else
                {
                    tcs.SetResult(new ClientResponse<RepPayload>(clientResponse));
                }
                return OCStackApplicationResult.OC_STACK_DELETE_TRANSACTION;
            };
            var gcHandle = GCHandle.Alloc(handler);
            callbackData.cb = handler;
            callbackData.context = GCHandle.ToIntPtr(gcHandle);
            
            IntPtr payloadHandle = IntPtr.Zero;
            if (resourceTypeName != null)
            {
                RepPayload payload = new RepPayload();

                payload.SetUri(_resourceUri);
                if (data != null)
                payload.PopulateFromDictionary(data);
                payload.AddResourceType(resourceTypeName);
                payloadHandle = payload.Handle;
            }

            var result = OCStack.OCDoResource(out _handle, method, _resourceUri, _address.OCDevAddr, payloadHandle, OCConnectivityType.CT_DEFAULT, OCQualityOfService.OC_LOW_QOS, callbackData, null, 0);
            OCStackException.ThrowIfError(result, "Failed to send to resource");
            var response = await tcs.Task.ConfigureAwait(false);
            
{'fraction_non_alphanumeric': 0.075617496895267, 'fraction_numerical': 0.0005519525320822409, 'mean_word_length': 2.467942583732057, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '654302', 'n_tokens_mistral': 1896, 'n_tokens_neox': 1809, 'n_words': 364}