//
//p-back.c
//
//Use to connect a pipe backwards.
//
//Connects the previous pipe in the opposite direction.
//That is read will effectively become write and vice versa.
//
//Basicly a hack to overcome a design shortfall.
//
//
//-UserX 2001/11/29

#include "pipe/backward.h"
#include "base/mem.h"


PipeBackward blankpipebackward = BLANKPIPEBACKWARD;

Pipe *pipebackwardMake(char *pipename, char *options) {
	PipeBackward *pb = memCopy(&blankpipebackward, sizeof(PipeBackward), "PipeBackward", NULL);//xiclone(&blankpipebackward, sizeof(PipeBackward));
	pipeInitFunctions((Pipe *) pb, 
			(PipeFuncIn) pipebackwardRead, (PipeFuncOut) pipebackwardWrite, 
			(PipeFuncAttach) pipebackwardAttach, (PipeFuncDetach) pipebackwardDetach, 
			(PipeFuncClose) pipebackwardClose, (PipeFuncStatus) pipebackwardStatus);
	pipeInit((Pipe *) pb);
	pipeInit(&pb->DummyPipe);
	return (Pipe *)pb;
}

void pipebackwardFree(PipeBackward *thispipe) {
	if(thispipe->BackwardPipe != NULL) {
		(thispipe->BackwardPipe->detachFunction)(thispipe->BackwardPipe);
	}

	pipeFree(&thispipe->IOPipe);
	pipeFree(&thispipe->DummyPipe);
	memFree(thispipe);//xifree(thispipe);
}

void pipebackwardRead(PipeBackward *thispipe, Pipe **errPipe) {
	*errPipe = pipeGenericRead(thispipe->IOPipe.backPipe);
	if(*errPipe == NULL) {
		//feed the input through the output of the backward pipe
		thispipe->BackwardPipe->outBuffer = dblockMoveAll(thispipe->BackwardPipe->outBuffer, thispipe->IOPipe.backPipe->inBuffer);
		pipeGenericWrite(thispipe->BackwardPipe);
		thispipe->IOPipe.inBuffer = dblockMoveAll(thispipe->IOPipe.inBuffer, thispipe->DummyPipe.outBuffer);
	}
}

void pipebackwardWrite(PipeBackward *thispipe, Pipe **errPipe) {
	//feed the output through the input of the backward pipe
	thispipe->DummyPipe.inBuffer = dblockMoveAll(thispipe->DummyPipe.inBuffer, thispipe->IOPipe.outBuffer);
	pipeGenericRead(thispipe->BackwardPipe);
	thispipe->IOPipe.backPipe->outBuffer = dblockMoveAll(thispipe->IOPipe.backPipe->outBuffer, thispipe->BackwardPipe->inBuffer);

	*errPipe = pipeGenericWrite(thispipe->IOPipe.backPipe);
}


void pipebackwardAttach(PipeBackward *thispipe) {
	//remember the pipe to make backwards
	thispipe->BackwardPipe = thispipe->IOPipe.backPipe;

	//remove the backpipe from the chain
	thispipe->IOPipe.backPipe = thispipe->BackwardPipe->backPipe;
	thispipe->IOPipe.backPipe->forwardPipe = (Pipe *)thispipe;
	thispipe->BackwardPipe->forwardPipe = NULL;
	thispipe->BackwardPipe->backPipe = &thispipe->DummyPipe;

}

void pipebackwardDetach(PipeBackward *thispipe) {
	pipebackwardFree(thispipe);
}

void pipebackwardClose(PipeBackward *thispipe) {
}

void pipebackwardStatus(PipeBackward *thispipe, int *status) {
	//normal read and write statuses are potentialy meaningless
	*status &= ~(PSTATUS_READ | PSTATUS_WRITE);

	//todo: replace this
	*status |= PSTATUS_READX | PSTATUS_WRITEX;

	*status |= (~(PSTATUS_READ | PSTATUS_WRITE | PSTATUS_READX | PSTATUS_WRITEX)) & pipeStatus(thispipe->BackwardPipe);
	//todo: call pipestatus on the backwardpipe and swap read and write flags.
}
