
#include "stdafx.h"

extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lkf5defs.h"
}

using namespace System;
using namespace System::Runtime::InteropServices;

#include "LKFDataProvider.h"

namespace lkfxdok {
	namespace c {
		LKFDataProvider::LKFDataProvider(ILKFFileDataProvider ^providerClass)
		{
			provider = providerClass;
			fileDelegate = gcnew LKFDataProviderFileDelegate(this, &LKFDataProvider::provider_file_callback);
		}

		int LKFDataProvider::provider_file_callback(int modelYear, const char *fileName, int buflen, char *buf) {
			
			String^ gcfileName = gcnew String(fileName);
			if (provider->ProvidesFile(modelYear, gcfileName) != 0) {
				Stream^ stream;
				try {
					stream = provider->GetFile(modelYear, gcfileName);
				}
				catch (Exception^ ex) {
					char* errc = (char*)Marshal::StringToHGlobalAnsi(ex->Message).ToPointer();
					strncpy(buf, errc, buflen);
					Marshal::FreeHGlobal((IntPtr)errc);
					return -1;
				}

				if (stream == nullptr) {
					char localbuf[2048];
					sprintf(localbuf, "NULL returned for %s from data provider", fileName);
					strncpy(buf, localbuf, buflen);
					return -1;
				}

				MemoryStream^ memoryStream = gcnew MemoryStream();
				stream->CopyTo(memoryStream);

				int len = (int) memoryStream->Length;

				if (len <= buflen) {
					array<unsigned char>^ arr = memoryStream->ToArray();
					Marshal::Copy(arr, 0, (IntPtr) buf, len);
				}
				if (len == 0) return 1;
				return len;
			}
			return 0;
		}

		void LKFDataProvider::Assign() {
			unmanagedFileDelegate = Marshal::GetFunctionPointerForDelegate (this->fileDelegate);
			::lkf_set_dataprovider((DATAPROVIDER_MODEL_FILE_FUNC) (void *) unmanagedFileDelegate);
		}

		void LKFDataProvider::Deassign() {
			::lkf_set_dataprovider(nullptr);
		}
	}
}
