/* Generated by Interface Builder */

#import "DetMagView.h"
#import "DetController.h"
#import "SmsObject.h"
#import <dpsclient/wraps.h>       // for PSxxx stuff
#import "PWfft.h"

#define WIDTH bounds.size.width
#define HEIGHT bounds.size.height

@implementation DetMagView

- initFrame:(const NXRect *)frameRect  
{
  self = [super initFrame: frameRect];
  userPath = newUserPath();
  fOffset = 0;
  
  return self;
}
  
- getTheSmsObject
{
  if (!winDelegate)
    winDelegate = [window delegate];

  if ([winDelegate respondsTo:@selector(getTheSmsObject)])
    return [winDelegate getTheSmsObject];
  else
    return NULL;
}

//-------------------------------------------------------------------
// - drawTrajectory  draw one trajectory of the SmsObject

- drawTrajectory:(int)iTraj:(int)posit
{
  id    theSmsObject = [self getTheSmsObject];
  int   FirstFrame = [winDelegate getFirstFrameMag], 
        LastFrame  = [winDelegate getLastFrameMag],
        ScaleAmp   = [winDelegate getDeterministicScale],
        NFrames = LastFrame - FirstFrame, i, iFrame = FirstFrame, incFrame = NFrames / 100;
  float LowestPartial = [winDelegate getLowestPartialMag], 
	HighestPartial = [winDelegate getHighestPartialMag],
	NPartials = HighestPartial - LowestPartial,
	SizeDisplay = 80 - (40 * NPartials / 50),
        fMag = 0, a, x, y,
        P1 = 30 + (posit - LowestPartial) * gSection, 
	P2 = 80 - 60 * (posit - LowestPartial) / NPartials, 
	HEIGHT100 = (HEIGHT - 100) / NFrames,
        BottomDb = [winDelegate getBottomDb], TopDb = [winDelegate getTopDb], 
	rangeDb = TopDb - BottomDb, 
	MagBottomDb = TO_MAG(BottomDb), MagrangeDb = TO_MAG(TopDb) - MagBottomDb;

  if (theSmsObject != NULL)
  {    
    beginUserPath(userPath, NO);
    if (incFrame < 1) incFrame = 1;
    for (iFrame = FirstFrame; iFrame <= LastFrame; iFrame = iFrame + incFrame)
       {
        i = iFrame - FirstFrame;
	x = P1 + i * fSection;
	y = HEIGHT100 * i + P2;
        UPmoveto(userPath, x, y);
        UPlineto(userPath, x, y);
       }

    iFrame = FirstFrame;
    fMag = [theSmsObject getDeterministicMag:iFrame iTraj:iTraj];
    i = (float)(iFrame - FirstFrame);
    if (fMag < BottomDb) fMag = BottomDb;
    if (fMag > TopDb) fMag = TopDb;
    if (ScaleAmp) 
         a = SizeDisplay * (TO_MAG(fMag)-MagBottomDb)/MagrangeDb; 
    else a = SizeDisplay *        (fMag-BottomDb)/rangeDb;
    UPmoveto(userPath, (P1 + i * fSection), (HEIGHT100 * i + a + P2));

    for (iFrame = FirstFrame+1; iFrame <= LastFrame; iFrame++)
       { 
        i = (float)(iFrame - FirstFrame);
        fMag  = [theSmsObject getDeterministicMag:iFrame iTraj:iTraj];
	if (fMag < BottomDb) fMag = BottomDb;
	if (fMag > TopDb) fMag = TopDb;
        if (ScaleAmp) 
             a = SizeDisplay * (TO_MAG(fMag)-MagBottomDb)/MagrangeDb; 
        else a = SizeDisplay *        (fMag-BottomDb)/(TopDb - BottomDb);
        UPlineto(userPath, (P1 + i * fSection), (HEIGHT100 * i + a + P2));
       }

    endUserPath(userPath, dps_ustroke);
    sendUserPath(userPath);
  }
  return self;
}

//-------------------------------------------------------------------
// - drawSelf:: - Draw the magnitude trajectories in the view

- drawSelf:(NXRect *)rects :(int)rectCount
{
  id    theSmsObject = [self getTheSmsObject];
  int   FirstFrame = [winDelegate getFirstFrameMag], 
        LastFrame = [winDelegate getLastFrameMag],
        NFrames = LastFrame - FirstFrame;
  float LowestPartial = [winDelegate getLowestPartialMag], 
        HighestPartial = [winDelegate getHighestPartialMag],
        NPartials = HighestPartial - LowestPartial;

  int iNTraj  = [theSmsObject getNTrajectories];
  int iNFrame = [theSmsObject getNRecords];
  int iTraj   = LowestPartial;
  int i, j, counter=0, iFormat, position[iNTraj];
  float Sum, Frq, min, lastmin = 0, Freq[iNTraj];
  float lowW = 30, lowH = 20, highH = 80;

  fSection =  (.35 * WIDTH) / NFrames;
  gSection =  (.6 * WIDTH) / NPartials;
  NXEraseRect(&bounds);
  PSsetlinewidth(0.0);
  PWinit();

  if (theSmsObject != NULL)
  {
    beginUserPath(userPath, NO);
    UPmoveto(userPath, lowW, highH);
    UPlineto(userPath, lowW+(.6 * WIDTH), lowH);
    endUserPath(userPath, dps_ustroke);
    sendUserPath(userPath);

    [self lockFocus];
    PWdrawX1ruler((int)(LowestPartial+1),(int)(HighestPartial+1),(int)2,2*gSection,-(120.0/NPartials));
    [self unlockFocus];

    iFormat = [theSmsObject getFormat];
    if (iFormat == FORMAT_HARMONIC || iFormat == FORMAT_HARMONIC_WITH_PHASE)
       while(iTraj <= HighestPartial)
        {
         [self drawTrajectory:iTraj:iTraj];
         iTraj++;
        }
    else
    {
    for (i = 0; i < iNTraj; i++)
     {
      Sum = 0;
      counter = 0;
      for (j = 0; j < iNFrame; j++)
        {
	  Frq = [theSmsObject getDeterministicFreq:j iTraj:i];
	  Sum = Sum + Frq;
          if (Frq > 0) counter++;
	}
      Freq[i] = (float) (Sum / counter);
     }
    for (i = 0; i < iNTraj; i++)
     {
      min = 22050.0;
      for (j = 0; j < iNTraj; j++)
        if (Freq[j] < min && Freq[j] > lastmin)
	 {
	  min = Freq[j];
	  counter = j;
	 }
      lastmin = min;
      position[i] = counter;
     }
    while(iTraj <= HighestPartial)
    {
      [self drawTrajectory:position[iTraj]:iTraj];
      iTraj++;
    }
   }
  }
  return self;
}

@end
