#ifndef ANSLLM_H
#define ANSLLM_H
#define ANSLLM_API __declspec(dllexport)
#pragma once
#include "LabVIEWHeader/extcode.h"
#include <map>
#include <string>
#include <memory>
#include "ANSLicense.h"
#include <CkAi.h>
//#include <CkRest.h>
//#include "CkAuthGoogle.h"
//#include "CkByteData.h"
//#include <CkAuthAws.h>
//#include <CkXml.h>
//#include <CkCrypt2.h>
//#include <CkSocket.h>
#include <opencv2/opencv.hpp>

namespace ANSCENTER {
	class ANSLLM_API ANSLLM {
	private:
		// Protects all shared mutable data
		mutable std::recursive_mutex _mutex;
		bool _isUnlockCodeValid{ false };
		bool _isLicenseValid{ false };
		bool _localLLM{ false };
		std::string _licenseKey;
		std::string _unlockCode;
		std::string _ollamaBaseUrl{ "http://localhost:11434/v1" };
		SPDLogger& _logger = SPDLogger::GetInstance("ANSLLM", false);
		CkAi ai;

	public:
		ANSLLM();
		~ANSLLM() noexcept;
		[[nodiscard]] bool Initialize(const std::string& licenseKey, bool localLLM = false);
		void CheckLicense();
		void CheckUnlockCode();

		bool SetLLMProvider(const std::string& llmProvider);
		[[nodiscard]] std::string GetLLMProvider();
		bool SetApiKey(const std::string& apiKey);
		[[nodiscard]] std::vector<std::string> GetModelList();
		bool SetTranscriptMode(bool transcriptMode);
		bool SetModel(const std::string& modelName);

		bool InputAddText(const std::string& inputText);
		bool InputAddImageUrl(const std::string& imageURL, const std::string& summary);
		bool InputAddImageFromPath(const std::string& filePath, const char* summary);
		bool InputAddImageFromBase64(const std::string& base64Image, const char* summary);

		bool InputAddFileURL(const std::string& fileURL, const char* summary);
		bool InputAddFileData(const std::string& filePath, const char* summary);
		bool ClearInputs();
		[[nodiscard]] std::vector<std::string> GetConversationList();

		bool CreateConversation(const std::string& systemMessage, const std::string& developerMessage, const std::string& conversationName);
		bool SetConversation(const std::string& conversationName);
		bool DeleteConversation(const std::string& conversationName);
		[[nodiscard]] std::string Ask(const std::string& prompt);


		// Other  methods and members
		bool SetUTF8(bool b);
		[[nodiscard]] bool GetUTF8();

		// PollAi
		[[nodiscard]] int PollAi(bool abort);

		// Local LLM methods
		bool SetLocalLLM(bool localLLM);
		bool SetOllamaBaseUrl(const std::string& baseUrl);
		bool SetBaseURL(const std::string& baseURL);
		[[nodiscard]] int  GetHeartbeatMs();
		bool SetHeartbeatMs(int heartbeatMs);

		[[nodiscard]] bool GetHostedConversation();
		bool SetHostedConversation(bool hostedConversation);

		[[nodiscard]] bool GetStreamingMode();
		bool SetStreamingMode(bool streamingMode);

		[[nodiscard]] int GetIdleTimeoutMs();
		bool SetIdleTimeoutMs(int idleTimeoutMs);

		bool SetSleepMs(int sleepMs);
		[[nodiscard]] std::string GetLastErrorMessage();

		// Parameters methods
		[[nodiscard]] std::string GetOutputText();
		[[nodiscard]] std::string GetOutputTextSb();

		bool SetAskParams(double temperature);
		//bool SetProviderParams(std::string providerParams);
	};
}

extern "C" ANSLLM_API int  CreateANSLLMHandle(ANSCENTER::ANSLLM** Handle, const char* licenseKey, int localLLM = 0);
extern "C" ANSLLM_API int  ReleaseANSLLMHandle(ANSCENTER::ANSLLM** Handle);

extern "C" ANSLLM_API int  SetANSLLMProvider(ANSCENTER::ANSLLM** Handle, const char* provider);
extern "C" ANSLLM_API int  GetANSLLMProvider(ANSCENTER::ANSLLM** Handle, LStrHandle provider);

extern "C" ANSLLM_API int  SetApiKey(ANSCENTER::ANSLLM** Handle, const char* apiKey);
extern "C" ANSLLM_API int  ANSLLMGetModelList(ANSCENTER::ANSLLM** Handle, LStrHandle modelList);
extern "C" ANSLLM_API int  ANSLLMSetTranscriptMode(ANSCENTER::ANSLLM** Handle, int transcriptMode);
extern "C" ANSLLM_API int  ANSLLMSetModel(ANSCENTER::ANSLLM** Handle, const char* modelName);

extern "C" ANSLLM_API int  ANSLLMInputAddText(ANSCENTER::ANSLLM** Handle, const char* inputText);
extern "C" ANSLLM_API int  ANSLLMInputAddImageUrl(ANSCENTER::ANSLLM** Handle, const char* imageURL, const char* summary);
extern "C" ANSLLM_API int  ANSLLMInputAddImageFromPath(ANSCENTER::ANSLLM** Handle, const char* filePath, const char* summary);
extern "C" ANSLLM_API int  ANSLLMInputAddImageFromBase64(ANSCENTER::ANSLLM** Handle, const char* base64Image, const char* summary);
extern "C" ANSLLM_API int  ANSLLMInputAddFileURL(ANSCENTER::ANSLLM** Handle, const char* fileURL, const char* summary);
extern "C" ANSLLM_API int  ANSLLMInputAddFileData(ANSCENTER::ANSLLM** Handle, const char* filePath, const char* summary);
extern "C" ANSLLM_API int  ANSLLMCreateConversation(ANSCENTER::ANSLLM** Handle, const char* systemMessage, const char* developerMessage, const char* conversationName);
extern "C" ANSLLM_API int  ANSLLMSetConversation(ANSCENTER::ANSLLM** Handle, const char* conversationName);
extern "C" ANSLLM_API int  ANSLLMAsk(ANSCENTER::ANSLLM** Handle, const char* prompt, LStrHandle response);

extern "C" ANSLLM_API int  ANSLLMClearInput(ANSCENTER::ANSLLM** Handle);
extern "C" ANSLLM_API int  ANSLLMGetConversationList(ANSCENTER::ANSLLM** Handle, LStrHandle conversationList);
extern "C" ANSLLM_API int  ANSLLMDeleteConversation(ANSCENTER::ANSLLM** Handle, const char* conversationName);
extern "C" ANSLLM_API int  ANSLLMSetUTF8(ANSCENTER::ANSLLM** Handle, int utf8Mode);
extern "C" ANSLLM_API int  ANSLLMGetUTF8(ANSCENTER::ANSLLM** Handle);
extern "C" ANSLLM_API int  ANSLLMPollAi(ANSCENTER::ANSLLM** Handle, int abort);
extern "C" ANSLLM_API int  ANSLLMSetLocalLLM(ANSCENTER::ANSLLM** Handle, int localLLM);
extern "C" ANSLLM_API int  ANSLLMSetOllamaBaseUrl(ANSCENTER::ANSLLM** Handle, const char* baseUrl);
extern "C" ANSLLM_API int  ANSLLMSetBaseURL(ANSCENTER::ANSLLM** Handle, const char* baseURL);

extern "C" ANSLLM_API int  ANSLLMSetHeartbeatMs(ANSCENTER::ANSLLM** Handle, int heartbeatMs);
extern "C" ANSLLM_API int  ANSLLMGetHeartbeatMs(ANSCENTER::ANSLLM** Handle);
extern "C" ANSLLM_API int  ANSLLMSetHostedConversation(ANSCENTER::ANSLLM** Handle, int hostedConversationMode);
extern "C" ANSLLM_API int  ANSLLMGetHostedConversation(ANSCENTER::ANSLLM** Handle);

extern "C" ANSLLM_API int  ANSLLMGetStreamingMode(ANSCENTER::ANSLLM** Handle);
extern "C" ANSLLM_API int  ANSLLMSetStreamingMode(ANSCENTER::ANSLLM** Handle, int streamingMode);
extern "C" ANSLLM_API int  ANSLLMGetIdleTimeoutMs(ANSCENTER::ANSLLM** Handle);
extern "C" ANSLLM_API int  ANSLLMSetIdleTimeoutMs(ANSCENTER::ANSLLM** Handle, int idleTimeoutMs);

extern "C" ANSLLM_API int  ANSLLMSetSleepMs(ANSCENTER::ANSLLM** Handle, int sleepMs);
extern "C" ANSLLM_API int  ANSLLMGetLastErrorMessage(ANSCENTER::ANSLLM** Handle, LStrHandle LastErrorMessage);
extern "C" ANSLLM_API int  ANSLLMGetOutputText(ANSCENTER::ANSLLM** Handle, LStrHandle outputText);
extern "C" ANSLLM_API int  ANSLLMGetOutputTextSb(ANSCENTER::ANSLLM** Handle, LStrHandle outputTextSb);


#endif
