/*  plotclone.C   */
/*  Copyright 1992 Mountain Math Software  */
/*  All Rights Reserved					*/

#include "iv_plot.h"
#include <string.h>
#include <complex.h>
#include <unistd.h>
#include "iv_graph.h"
#include <InterViews/window.h>
#include <InterViews/leave-scope.h>
#include "coord.h"
#include "plotdatg.h"
#include "newaloc.h"
#include "usercom.h"
#include "arthtyp.h"

#include "shared.h"
#include "remcom.h"
// #include "winmgr.h"
#include "wfiles.h"
// #include "winpres.h"
// #include "plot.h"
// #include "labplot.h"
#include "help.h"
#include "plotfile.h"
#include "dsp_app.h"

// void TestAlloc(const char * Msg=0);

void DataPlot::clone(Transform tr)
{
	// TestAlloc("DataPlot::clone entry");
	if (cloned_from) {
		cloned_from->clone(tr);
		return ;
	}
	
	DspApplication::disable_remote_com();
	while (ThePlotsManager->to_complete()) {
		DspApplication::enable_remote_com();
		while (ThePlotsManager->to_complete()) ReadSeg->CheckPacketRead();
		DspApplication::disable_remote_com();
	}
	// LogOut << "clone start for `" << GetCaption() << "'.\n" ;

	// TestAlloc("DataPlot::clone start");
	int plot_id = ThePlotsManager->GetPlotId();

	AxisScalingX Temp = GetScaleX();
	SetScaleX(OriginalScaleX);
	StrDataPlotHeader * StrPlotHead = GetStructure();
	SetScaleX(Temp);

	// StrPlotHead->Dump();
	StrPlotHead->PlotChannelToSet = 0 ;
	StrPlotHead->PlotIdentifier = plot_id ;
	// StrPlotHead->Dump();
	// TestAlloc("DataPlot::clone before add");
	ThePlotsManager->AddRemotePlot(sizeof(*StrPlotHead),(char *) StrPlotHead,
		tr);
	// TestAlloc("DataPlot::clone after add");
	// delete StrPlotHead ;
	// TestAlloc("DataPlot::clone after delete");

	if (GetCaption())ThePlotsManager->AddRemotePlotCaption(
		1+strlen(GetCaption()),GetCaption());

	ThePlotsManager->AddRemotePlotName(1+strlen(GetName()),GetName());

	// TestAlloc("DataPlot::clone after caption");
	
	DataPlot * this_plot = ThePlotsManager->to_complete();
	this_plot->cloned_from = this ;
	clones.Append(this_plot);

	for (int i = 0 ; i < GetNumberOfChannels() ; i++) {
		GetChannel(i)->clone(plot_id);
		// TestAlloc("DataPlot::clone after clone channel");
	}
	ThePlotsManager->UpdateControl(plot_id,PlotControlComplete,0,0,0);
	this_plot->set_from_clone();
	// TestAlloc("DataPlot::clone after update control");
	// this_plot->PlotPage(0);
	// LogOut << "clone end for `" << GetCaption() << "'.\n" ;
	DspApplication::enable_remote_com();
	// LogOut << "fist_page_plotted = " << is_first_page_plotted() << "\n" ;
}

void PlotChannelPointer::clone(int plot_id)
{
	DataPlot * parent = ThePlotsManager->to_complete();
	DataPlot::Transform tr = parent->the_transform ;

	StrPlotChannel * StrPlotChan = &(GetStructure());

	// StrPlotChan->Dump();
	StrPlotChan->MultiplexedElementToSet = 0 ;
	// StrPlotChan->Dump();

	if ((tr == DataPlot::power || tr == DataPlot::db_power) &&
		StrPlotChan->NumberMultiplexedElements == 2)
		StrPlotChan->NumberMultiplexedElements = 1 ;
	int Elements = StrPlotChan->NumberMultiplexedElements;
	StrPlotChan->ThePlotArithType = ArithType::ArithDouble ;

	// StrPlotChan->Dump();

	ThePlotsManager->AddRemotePlotChannel(sizeof(*StrPlotChan),
		(char *) StrPlotChan);
	delete StrPlotChan ;

	MultiplexedElement * Element = GetMultiplexedElements() ;
	
	for (int EltIndex = 0 ; EltIndex < Elements; EltIndex++) {
		StrMultiplexedElement * StrElement =
			&(Element[EltIndex].GetStructure());
		ThePlotsManager->AddRemoteMultiplexedElement(sizeof(*StrElement),
			(char *) StrElement);
		delete StrElement ;
	}

}

void DataPlot::set_from_clone()
{
	for (int i = 0 ; i < GetNumberOfChannels(); i++) 
		GetPlotChannel(i)->set_from_clone(cloned_from->GetPlotChannel(i));
}

int DataPlot::check_init()
{
/*
 *	LogOut << "DataPlot::check_init for `" << GetDataFile(0)->GetName()
 *		<< "' SampleIndexLastPlotUpdate = " << SampleIndexLastPlotUpdate
 *		<< "\n" ;
 */
	// LogOut << "cloned from = " << (void *) cloned_from << "\n" ;
	if (cloned_from) if (SampleIndexLastPlotUpdate == -1) {
		long samples = (long) GetNumberSamplesInPlot() ;
		for (int i = 0 ; i < GetNumberOfChannels(); i++) {
			PlotChannelPointer *cloned_from_chan =
				cloned_from->GetPlotChannel(i);
			PlotChannelPointer *this_chan = GetPlotChannel(i);
			long available = cloned_from_chan->GetDataFile()->
				GetNextByteToWrite() /
				((DataFileClone *)(this_chan->GetDataFile()))->
				get_word_factor() ;
			long seek_to = cloned_from_chan->size_of() * samples ;
			// LogOut << "seeking to " << seek_to << "\n" ;
			if (seek_to > available) return 0 ;
			// LogOut << "seeking to " << seek_to << "\n" ;
			this_chan->GetDataFile()->Seek(seek_to);
		}

		the_graph->set_y_tick_spacing();

		// LogOut << "Before PlotPage(0), for `" << GetCaption() << "'\n" ;
		PlotPage(0);
		// LogOut << "After PlotPage(0), for `" << GetCaption() << "'\n" ;
		return 1 ;
	}
	return 0 ;
}

void PlotChannelPointer::set_from_clone(PlotChannelPointer * cloned_from)
{
	SampleRateAdjustment = cloned_from->GetSampleRateAdjustment() ;
}

void PlotChannelPointer::UpdateMax(int i, double val)
{
	int did_change = 0 ;
	if (ThePlot->is_eye_plot() && !(i&1)) {
		if (val < MinXVal) {MinXVal = val ; did_change = 1;}
		if (val > MaxXVal) {MaxXVal = val; did_change = 1;}
	} else {
		if (val < MinYVal) {MinYVal = val ; did_change = 1;}
		if (val > MaxYVal) {MaxYVal = val; did_change = 1;}
	}
	if (did_change) {
/*
 *		LogOut << "PlotChannelPointer::UpdateMax(" << i << ", " << val <<
 *			") doing damage\n" ;
 *		LogOut << ThePlot->GetCaption() << "\n" ;
 */
		GetPlot()->ResetData();
	}
	
}


int32 DataPlot::last_sample_index()
{
	if (cloned_from) return cloned_from->last_sample_index();
	// For two dimensional plots get the highest block index
	// For other plots get the highest common sample time, subtract the
	//	start time and divide by the sample rate of the reference channel
	// ComputeRegionToUpdate();
/*
 *	LogOut << "BlockSize = " << GetBlockSize() << ", is two dim = " <<
 *		is_two_dimensional() << "\n" ;
 */
	int32 StartBlock ;
	if (GetBlockSize() < 2) StartBlock = LargestIndexAvailableToPlot ;
	else StartBlock = LargestIndexAvailableToPlot/GetBlockSize();
	// LogOut << "DataPlot::last_sample_index returning " << StartBlock << "\n" ;
	return StartBlock ;
}

int32 DataPlot::samples_in_plot()
{
	// for two dimensional plots return 1,
	// for other return number of samples in plot
	if (is_two_dimensional() && GetBlockSize() > 1) {
		return 1 ;
	}
	return (int32) GetNumberSamplesInPlot() ;
}

void DataPlot::plot_sample(int32 index)
{
	// LogOut << "plot_sample(" << index << ")\n" ;
	// treat this as a block index for two dimensional plots and a
	// sample index for other plots
	PlotPage(index) ;
}

int32 DataPlot::current_sample()
{
	// return block index for two dimensional plots and referenc sample index
	// for others
	return GetCurrentSample() ;
}

void DataPlot::raise_window()
{
	DataPlotListIterator Next(clones);
	DataPlot * plot ;
	while (plot = Next()) plot->raise_window();
	the_graph->raise_window();
}

const char * DataPlot::transform_name()
{
    switch(the_transform) {
case DataPlot::none:
        return 0 ;
case DataPlot::power:
        return "Power" ;
case DataPlot::db:
        return "Decibel" ;
case DataPlot::db_power:
        return "Decibel power" ;
case DataPlot::spectral:
        return "Spectral" ;
case DataPlot::copy :
        return "Copy" ;
default:
        DbgError("transform_name","bad type");
    }
    return 0 ;

}
