#include "Header.h"
#include "GlobHdr.h"
#include "Mem.h"
#include "TimLib:Seq.h"
#include "FStream.h"
#include <stdlib.h>
#include <string.h>

GlobHdr* Glb = NULL;

#ifndef MAKEABS
static const _kernel_oserror Err_UnknownParamCode =
{ErrNum_ParamsError, "Unknown parameter code."};
#endif

_kernel_oserror* Module_Initialize(const char* cmd_tail, int podule_base, void* pw)
{
	const _kernel_oserror* e;

	IGNORE(cmd_tail);
	IGNORE(podule_base);

	Glb = calloc(1, sizeof(*Glb));

	Glb->pw = pw;
	Glb->pmodname = Module_Title;
	Glb->cfg.inputbufsize = 256;
	Glb->cfg.outputbufsize = 1024;
	Glb->cfg.audiocastport = 7777;
	Glb->cfg.buffering = 1;
#ifndef MAKEABS
	e = CMem_Init(Glb, 1*1024*1024);
#else
	e = CMem_Init(Glb, 0);
#endif
	if (!e)
	{
#ifndef MAKEABS
		e = CSeq_Init(Glb);
#endif
		if (!e) Streams_Init(Glb, pw);

		if (e) CMem_Finalize(Glb);
	}

	return (_kernel_oserror*) e;
}

_kernel_oserror* Module_Finalize(int fatal, int podule, void* pw)
{
	const _kernel_oserror* e = NULL;

	IGNORE(fatal);
	IGNORE(podule);

#ifndef MAKEABS
	e = CSeq_AllowFinalize(Glb);
#endif
	if (!e) e = Streams_Finalise(Glb, pw);
	if (e) return (_kernel_oserror*) e;

#ifndef MAKEABS
	CSeq_Finalize(Glb);
#endif
	CMem_Finalize(Glb);

	free(Glb);
	Glb = NULL;

	return NULL;
}

#ifndef MAKEABS
void Module_Service(int service_number, _kernel_swi_regs* r, void* pw)
{
	IGNORE(pw);

	if (service_number != 0x54) return;

	CSeq_SoundService(Glb, r);
}

static const _kernel_oserror* swi_Version(GlobHdr* g, _kernel_swi_regs* r)
{
	IGNORE(g);

	r->r[0] = Module_VersionNumber;

	return NULL;
}

/*
 * SWI Configure
 *
 * In  - R0 code
 *       R1 value
 *
 * Out - R1 current value
 */
static const _kernel_oserror* swi_Configure(GlobHdr* g, _kernel_swi_regs* r)
{
	if (r->r[0] == -1)
	{
		// close all streams
		Streams_CloseAll(g);
		return NULL;
	}
	else if ((r->r[0] < 128) || (r->r[0] == 255))
		return CSeq_Configure(g, r);
	else
		return swi_Configure_Streams(g, r);
}

static const _kernel_oserror* swi_Decoding(GlobHdr* g, _kernel_swi_regs* r)
{
	switch (r->r[0])
	{
		case 0: // total amount of data read on the net in bytes
		{
			int64_t* ppos = (int64_t*) r->r[1];
			*ppos = g->HttpReadBytes;
		}
		break;
		default: return &Err_UnknownParamCode;
	}

	return NULL;
}

_kernel_oserror* Module_Swis(int swi_offset, _kernel_swi_regs* r, void* pw)
{
	IGNORE(pw);

	switch(swi_offset)
	{
		case 0x00: return (_kernel_oserror*) swi_Version(Glb, r);
		case 0x01: return (_kernel_oserror*) swi_Configure(Glb, r);
		case 0x02: return (_kernel_oserror*) swi_FileOpen(Glb, r);
		case 0x03: return (_kernel_oserror*) swi_StreamClose(Glb, r);
		case 0x04: return (_kernel_oserror*) swi_StreamCreate(Glb, r);
		case 0x05: return (_kernel_oserror*) swi_StreamSource(Glb, r);
		case 0x06: return (_kernel_oserror*) swi_StreamReceiver(Glb, r);
		case 0x07: return (_kernel_oserror*) swi_Decoding(Glb, r);

		case 0x08: return (_kernel_oserror*) swi_StreamPlay(Glb, r);
		case 0x09: return (_kernel_oserror*) swi_StreamPause(Glb, r);
		case 0x0a: return (_kernel_oserror*) swi_StreamStop(Glb, r);
		case 0x0b: return (_kernel_oserror*) swi_StreamPosition(Glb, r);
		case 0x0c: return (_kernel_oserror*) swi_StreamVolume(Glb, r);
		case 0x0d: return (_kernel_oserror*) swi_StreamIsReady(Glb, r);
		case 0x0e: return (_kernel_oserror*) swi_StreamStatus(Glb, r);
		case 0x0f: return (_kernel_oserror*) swi_StreamChain(Glb, r);

		case 0x10: return (_kernel_oserror*) swi_StreamInfo(Glb, r);
		case 0x11: return (_kernel_oserror*) swi_StreamTexts(Glb, r);
		case 0x12: return (_kernel_oserror*) swi_StreamParam(Glb, r);
		case 0x13: return (_kernel_oserror*) swi_StreamDecoding(Glb, r);
		case 0x14: return (_kernel_oserror*) swi_ChannelParams(Glb, r);
		case 0x15: return (_kernel_oserror*) swi_ChannelStatus(Glb, r);
		case 0x3f: return (_kernel_oserror*) swi_GetMixingInfo(Glb, r);
	}

	return error_BAD_SWI;
}
#endif
