#include <string.h>
#include <unistd.h>
#include "yacintfc.h"
#include "outfile.h"
#include "outnode.h"
#include "cgidbg.h"
#include "drvout.h"
#ifdef __NT_VC__
#include <io.h>
#endif
#if !defined(TI_C30) && !defined(__NT_VC__)
#define O_BINARY 0
#endif
#include <fcntl.h>
#include <stdlib.h>
#include "ramio.h"
#include "sysconst.h"
#include "remcom.h"
#include "rtktest.h"
#include "environ.h"

int OutputNode::read_binary()
{
	return binary_read_flag ;
}

#ifdef INTERACTIVE
int OutputNode::InitAfterLinked()
{
    return set_read_binary_flag(binary_read_flag) ;
}

void OutputNode::input_linked(int )
{
	// after one channel is linked set all other channels to be
	// identical
	if (already_set) return;
	already_set = 1 ;
	ArithType::ArithCapabilities typ = 
		(ArithType::ArithCapabilities) ArithType::ArithTypeUndefined ;
	for (int i = 0 ; i < GetIn() ; i++) {
		typ = GetInStream(i)->GetArithType();
		if (typ != ArithType::ArithCapabilityAny) break ;
	}
	if (typ ==  ArithType::ArithTypeUndefined) {
		State.Error("no arithmetic type set, cannot link node");
		return ;
	}
	
	for (i = 0 ; i < GetIn() ; i++)  GetInStream(i)->SetArithType(typ) ;
}
#endif



void OutputNode::FileInit()
{
	TheOutputFile = new OutputFile(this,GetFileName());
	FileName_1 = TheOutputFile->GetFileName();
}



void OutputNode::Ctor()
{
	TheOutputFile = 0 ;
	TheNetworkReader = 0 ;
	if (!GetFileName()) SetFileName(GetName());
	TheReaderOutputInterface = &DefaultDriverOutputInterface ;
#ifdef INTERACTIVE
	if (State.IsInteractive()) FileInit();
#else
	FileInit();
	#endif
}

ErrCode OutputNode::NodeReset()
{
	ErrCode Return = OK ;
	// LogOut << "OutputNode::NodeReset() for `" << GetName() << "'\n" ;
	if (TheOutputFile) {
		// LogOut << "Calling TheReaderOutputInterface\n" ;
		MachWord x = (MachWordCast) 0 ;
		if (TheReaderOutputInterface(this, ResetDriverSystemInterface,
			0, &x) < 0) return FatalError ;
		ErrCode Loc = TheOutputFile->Reset();
		if (Loc > Return) Return = Loc ;
	}
	return Return ;
}

ErrCode OutputNode::TheKernel(int32 k)
{
	// LogOut << "OutputNode::TheKernel(" << k << ")\n" ;
	ErrCode Ret = OK ;
	ErrCode Loc ;
#ifdef INTERACTIVE
	if (!TheOutputFile) {
		FileInit() ;
		if (!TheOutputFile->CreateOk()) {
			delete TheOutputFile ;
			TheOutputFile = 0 ;
			// LogOut << "returning FatalError\n" ;
			return FatalError ;
		}
	}
#endif
	ErrCode Return = OK ;
	int32 block_size = GetBlockSize();
	if (!block_size) block_size = 1 ;
	int32 SaveTotal = k * block_size * GetInEltSize() * GetDeltaIn();
	// LogOut << "SaveTotal = " << SaveTotal << "\n" ;
	int32 DataSize ;
	for (int Chan = 0; Chan < GetIn(); Chan++) {
	    int32 Left = SaveTotal ;
	    while(DataSize = GetContiguousAvailableData(Chan)) {
			// LogOut << "DataSize = " << DataSize << ", chan = " << Chan <<
				"\n" ;
			if (DataSize > Left) DataSize = Left ;
			if (DataSize < 1) break ;
			const MachWord * Ptr  = GetReadPtr(Chan);
			// LogOut << "DataSize = " << DataSize << "\n" ;
			int32 DataWritten = TheReaderOutputInterface(this,Chan,DataSize,
				(MachWord *) Ptr) ;
			// LogOut << GetName() << " wr " << DataWritten << "\n" ;
			if (DataWritten < 1) {
				Return = EndOfData ;
				break ;
			} else {
				UpdateRead(DataWritten,Chan);
				Left -= DataWritten ;
			}
        }
	}
	// LogOut << "Returning " << Return << "\n" ;
	return Return ;
}

void OutputNode::Dtor()
{
	// LogOut << "OutputNode::Dtor for `" << GetName() << "'\n" ;
	delete TheOutputFile ;
	SetFileName(0);
}

