/*
 * Copyright (C) 2018 "IoT.bzh"
 * Author Jonathan Aillet <jonathan.aillet@iot.bzh>
 *
 * 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.
 */

#ifndef _HAL_UTILITIES_DATA_INCLUDE_
#define _HAL_UTILITIES_DATA_INCLUDE_

#include <stdio.h>

#include <urcu/list.h>

#include <wrap-json.h>

#include <afb/afb-binding.h>

#include <ctl-config.h>

#include "4a-hal-utilities-alsa-data.h"

#define HAL_UNKNOWN_DEVICE	-1

#define HAL_STREAM_UPDATES_EVENT_NAME		"stream-updates"

// Enum for linked list type
enum LinkedListType {
	LINKED_LIST_FOR_DEPENDENCIES_DATA = 0,
	LINKED_LIST_FOR_MIXER_DATA = 1,
	LINKED_LIST_FOR_HAL_DATA = 2
};

// Enum for hal status
enum HalStatus {
	HAL_STATUS_UNAVAILABLE = 0,
	HAL_STATUS_AVAILABLE = 1,
	HAL_STATUS_READY = 2
};

// Enum for probed devices (dependencies) class
enum ProbedDeviceClasses {
	INVALID_PROBED_DEVICE = 0,
	STATIC_PROBED_DEVICE = 1,
	DYNAMIC_PROBED_DEVICE = 2,
	MANDATORY_PROBED_DEVICE = 3
};

// Enum for probed devices (dependencies) info format requested
enum DependencyInfoJsonFormat {
	DEPENDENCY_COMPACT_JSON = 0,
	DEPENDENCY_FULL_JSON = 1
};

// Enum for probed devices (dependencies) info format requested
enum DependencyStatus {
	UNAVAILABLE_DEPENDENCY = 0,
	AVAILABLE_DEPENDENCY = 1,
	ALL_DEPENDENCY = 2
};

// Structure to store data for audio devices validated by dependencies
struct InternalHalDeviceData {
	int cardNb;
	char *cardId;
	char *cardShortName;
	char *cardLongName;
	char *cardDriver;
	char *cardMixerName;
	char *cardComponents;
	int playbackDeviceNb;
	char *playbackDeviceId;
	char *playbackDeviceName;
	char *extendedCardNb;
};

// Structure to store one provided dependency
struct InternalHalProbedDevice {
	char *uid;
	enum ProbedDeviceClasses deviceClass;
	json_object *requestedDeviceJ;

	struct InternalHalDeviceData *deviceData;

	struct cds_list_head node;
};

// Structure to store stream data
struct InternalHalMixerData {
	char *verb;
	char *verbToCall;
	char *streamCardId;
	afb_event_t event;

	struct cds_list_head node;
};

// Structure to store specific internal hal data
struct InternalHalData {
	char *mixerApiName;
	char *prefix;
	json_object *halMixerJ;

	struct cds_list_head probedDevicesListHead;

	struct cds_list_head streamsDataListHead;
	afb_event_t streamUpdates;

	struct InternalHalAlsaMapT *alsaMapT;

	afb_api_t apiHandle;
	CtlConfigT *ctrlConfig;
};

// Structure to store specific hal (internal or external) data
struct HalData {
	char *apiName;
	enum HalStatus status;
	char *sndCardPath;
	int sndCardId;
	char *uid;
	char *info;
	unsigned int internal;

	char *author;
	char *version;
	char *date;
	// Can be beefed up if needed

	struct InternalHalData *internalHalData;		// Can be NULL if external api

	struct cds_list_head node;
};

// Structure to store hal manager data
struct HalMgrData {
	char *apiName;
	char *info;

	afb_api_t apiHandle;

	struct cds_list_head halDataListHead;
};

// Internal Hal - Probed devices structure handling functions
enum ProbedDeviceClasses HalUtlGetProbedDeviceClassFromString(char *probedDeviceString);
char *HalUtlGetProbedDeviceClassString(enum ProbedDeviceClasses deviceClass);
struct InternalHalProbedDevice *HalUtlAddProbedDeviceToProbedDeviceList(struct cds_list_head *probedDevicesListHead);
int HalUtlRemoveSelectedProbedDeviceFromList(struct cds_list_head *probedDevicesListHead,
					     struct InternalHalProbedDevice *probedDeviceToRemove);
int HalUtlRemoveAllProbedDevicesFromList(struct cds_list_head *probedDevicesListHead);
int HalUtlGetNumberOfProbedDevicesInList(struct cds_list_head *probedDevicesListHead);
struct InternalHalProbedDevice *HalUtlSearchProbedDeviceDataById(struct cds_list_head *probedDevicesListHead,
								 char *uid);
struct InternalHalDeviceData *HalUtlAllocateAndFillProbedDeviceDataUsingInfoGetResponse(json_object *responseJ);
json_object *HalUtlGetJsonForSpecificDependencies(afb_api_t apiHandle,
						  struct InternalHalProbedDevice *requestedProbedDevice,
						  enum DependencyInfoJsonFormat jsonFormat);
json_object *HalUtlGetJsonForSpecificDependenciesUsingUid(afb_api_t apiHandle,
							  struct cds_list_head *probedDevicesListHead,
							  char *uid,
							  enum DependencyInfoJsonFormat jsonFormat);
json_object *HalUtlGetJsonArrayForAvailableDependencies(afb_api_t apiHandle,
							struct cds_list_head *probedDevicesListHead,
							enum DependencyInfoJsonFormat jsonFormat);
json_object *HalUtlGetJsonArrayForAllDependencies(afb_api_t apiHandle,
						  struct cds_list_head *probedDevicesListHead,
						  enum DependencyInfoJsonFormat jsonFormat);

// Internal Hal - Streams data handling functions
struct InternalHalMixerData *HalUtlAddMixerDataToMixerDataList(struct cds_list_head *mixerDataListHead);
int HalUtlRemoveSelectedMixerData(struct cds_list_head *mixerDataListHead,
				  struct InternalHalMixerData *mixerDataToRemove);
int HalUtlRemoveAllMixerData(struct cds_list_head *mixerDataListHead);
int HalUtlGetNumberOfMixerDataInList(struct cds_list_head *mixerDataListHead);
struct InternalHalMixerData *HalUtlSearchMixerDataByProperties(struct cds_list_head *mixerDataListHead,
							       char *verb,
							       char *verbToCall,
							       char *streamCardId);
json_object *HalUtlGetJsonArrayForSpecificMixerData(afb_api_t apiHandle, struct InternalHalMixerData *mixerData);
json_object *HalUtlGetJsonArrayForAllMixersData(afb_api_t apiHandle, struct cds_list_head *mixerDataListHead);

// Hal data handling functions
struct HalData *HalUtlAddHalToHalList(struct cds_list_head *halDataListHead);
int HalUtlRemoveSelectedHalFromList(struct cds_list_head *halDataListHead, struct HalData *halToRemove);
int HalUtlRemoveAllHalFromList(struct cds_list_head *halDataListHead);
int HalUtlGetNumberOfHalInList(struct cds_list_head *halDataListHead);
struct HalData *HalUtlSearchHalDataByApiName(struct cds_list_head *halDataListHead, char *apiName);

// Hal Manager data handling functions
int HalUtlInitializeHalMgrData(afb_api_t apiHandle, struct HalMgrData *halMgrData, char *apiName, char *info);
void HalUtlRemoveHalMgrData(struct HalMgrData *halMgrData);

#endif /* _HAL_UTILITIES_DATA_INCLUDE_ */