// ObjectWindows - (C) Copyright 1992 by Borland International

/* MITOSM.CPP  Mitochondrial statistics simulation, derived from STEPS4.CPP */
/*    this version creates a smooth image */

#include <owl.h>
#include <edit.h>
#include <checkbox.h>
#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <inputdia.h>
#include <time.h>
#include <alloc.h>
#include <math.h>
#include "greywin.h"
#include "mitodlg.h"

#define APPNAME "Mitochondrial Statistics"

void Make_Gaussian_Mask(int, int);
void SplitPixel(int, int, int, int, int, unsigned char far**,
	BOOL smooth, int);
void Free_Gaussian_Mask(int);
void fftnorm(unsigned char far **image1, unsigned char far **image2, int width, int height);

class TMyApp : public TApplication
{
public:
  TMyApp(LPSTR AName, HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
    : TApplication(AName, hInstance, hPrevInstance, lpCmdLine, nCmdShow) {};
  virtual void InitMainWindow();
};

_CLASSDEF(TMyWindow)
class TMyWindow : public TDialog //TWindow
{
public:
  HDC DragDC;
	int Nsteps;   	// number of splits:  2^Nsteps = width of image
	long value_sum;
	unsigned char far **Window_Data;
	TEdit *Steps_Input_Box, *Levels_Input_Box;
	TCheckBox *Make_Window_Box, *Smooth_Box, *FFT_Box;
  TGreyWindow *Last_Window;
	
	TMyWindow(PTWindowsObject AParent, LPSTR AName, PTModule AModule);
  ~TMyWindow();
  /* virtual BOOL CanClose();
	virtual void WMRButtonDown(RTMessage Msg)
	= [WM_FIRST + WM_RBUTTONDOWN];     */
  virtual void SetupWindow();
	virtual void WMRButtonDown(RTMessage Msg) = [ID_FIRST + DL_GO];
	virtual void Exit(RTMessage Msg) = [ID_FIRST + DL_EXIT];
	virtual void Set_Check(RTMessage Msg) = [ID_FIRST + DL_MAKENEWWINDOW];
	virtual void Set_Smooth(RTMessage Msg) = [ID_FIRST + DL_SMOOTH];
  virtual void Set_FFT(RTMessage Msg) = [ID_FIRST + DL_FFT];
  void ClearData();
};

TMyWindow::TMyWindow(PTWindowsObject AParent, LPSTR AName, PTModule
		AModule)
	: TDialog(AParent,AName,AModule)
					 // Twindow(AParent, ATitle)
{
	int i,k;

	Nsteps = 6;
	value_sum = 0;
	Window_Data = (unsigned char far **)
			malloc(WINHEIGHT * sizeof(unsigned char far *));
	for (i=0 ; i<WINHEIGHT ; i+=LINES_PER_BLOCK)
  {
		Window_Data[i] = (unsigned char far *)
			malloc(LINES_PER_BLOCK * WINWIDTH * sizeof(unsigned char));
		for (k=i+1 ; k<i+LINES_PER_BLOCK ; k++)
			Window_Data[k] = Window_Data[k-1] + WINWIDTH;
	}
	ClearData();
	Steps_Input_Box = new TEdit(this, DL_DATA1, (WORD) 20, NULL);
	Levels_Input_Box = new TEdit(this, DL_DATA2, (WORD) 20, NULL);
	Make_Window_Box = new TCheckBox(this, DL_MAKENEWWINDOW, NULL, NULL);
  Smooth_Box = new TCheckBox(this, DL_SMOOTH, NULL, NULL);
	FFT_Box = new TCheckBox(this, DL_FFT, NULL, NULL);
}

void TMyWindow::SetupWindow()
{
	TDialog::SetupWindow();

	/* set up dialog boxes */
	Make_Window_Box->Uncheck();
  FFT_Box->Uncheck();
  Smooth_Box->Check();
	Steps_Input_Box->SetText("7");
	Levels_Input_Box->SetText("7");
	Last_Window = NULL;
}

void TMyWindow::ClearData()
{
	int i,j;

	for (i=0 ; i<WINHEIGHT ; i++)
  	for (j=0 ; j<WINWIDTH ; j++)
			Window_Data[i][j] = (unsigned char) 0;
}

TMyWindow::~TMyWindow()
{
	int i;

	for (i=0 ; i<WINHEIGHT ; i+=LINES_PER_BLOCK)
  	free(Window_Data[i]);
	free(Window_Data);

	delete Steps_Input_Box;
	delete Levels_Input_Box;
	delete Make_Window_Box;
	delete Smooth_Box;
	delete FFT_Box;
}

void TMyWindow::Exit(RTMessage Msg)
{
	CloseWindow();
}

void TMyWindow::Set_Check(RTMessage Msg)
{
	Make_Window_Box->Toggle();
}

void TMyWindow::Set_Smooth(RTMessage Msg)
{
	Smooth_Box->Toggle();
}

void TMyWindow::Set_FFT(RTMessage Msg)
{
	FFT_Box->Toggle();
}

void TMyWindow::WMRButtonDown(RTMessage Msg)
{
  char InputText[20], OutputText[100];
	TGreyWindow *GreyWindow;
	int i, j, value, tlen, tnum, Width, Max_Levels;
	BOOL Make_New_Window, Make_Smooth=TRUE, Make_FFT;
	double win_mean, win_sd, f_value;
  unsigned char far **image2;

	Steps_Input_Box->GetText(InputText, sizeof(InputText));
	Nsteps = atoi(InputText);
	Levels_Input_Box->GetText(InputText, sizeof(InputText));
  Max_Levels = atoi(InputText);
	if (Make_Window_Box->GetCheck() == BF_CHECKED) Make_New_Window = TRUE;
  else Make_New_Window = FALSE;
	if (Smooth_Box->GetCheck() == BF_CHECKED) Make_Smooth = TRUE;
  else Make_Smooth = FALSE;
	if (FFT_Box->GetCheck() == BF_CHECKED) Make_FFT = TRUE;
  else Make_FFT = FALSE;

	value_sum = 0;
  Width = 1<< Nsteps;

	ClearData();
	/* mitochondrial field */
	if (Make_Smooth) Make_Gaussian_Mask(Width, Width);
	SplitPixel((int) 127, 0, 0, 0, Nsteps, Window_Data, Make_Smooth, Max_Levels);
	if (Make_Smooth) Free_Gaussian_Mask(Width);
	
	/* get statistics */
	win_mean = 0.0;
	win_sd = 0.0;
	for (i=0 ; i<(1<<Nsteps) ; i++)
		for (j=0 ; j<(1<<Nsteps) ; j++)
		{
			win_mean += (double) Window_Data[i][j];
			win_sd += (double) Window_Data[i][j] * (double) Window_Data[i][j];
		}
	win_mean /= (double) (((long) 1) << (2*Nsteps));
	win_sd /= (double) (((long) 1) << (2*Nsteps));
	win_sd = sqrt(win_sd - (win_mean * win_mean));

	/* show iid random field for comparison */
	for (i=0 ; i<(1<<Nsteps) ; i++)
		for (j=(1<<Nsteps) ; j<(2<<Nsteps) ; j++)
		{
			f_value = (double) random(2*MAXGREY) - MAXGREY;
			f_value *= win_sd / (sqrt(0.33) * MAXGREY);
			f_value += win_mean;
			if (f_value < 0.0) f_value = 0.0;
      if (f_value > 255.0) f_value = 255.0;
			Window_Data[i][j] = (unsigned char) f_value;
		}

	if (Make_FFT)
	{
  	/* make pointer to second half of window as an array */
  	image2 = (unsigned char **) malloc((1<<Nsteps) * sizeof(unsigned char *));
		for (i=0 ; i<(1<<Nsteps) ; i++) image2[i] = Window_Data[i] + (1<<Nsteps);
		fftnorm(Window_Data, image2, (1<<Nsteps), (1<<Nsteps));
	}

	if (Make_New_Window || (Last_Window == NULL))
  {
		GreyWindow = new TGreyWindow(NULL, "Greyscale Window", Window_Data);
		if ((GetApplication()->MakeWindow(GreyWindow)) == NULL)
			MessageBox(HWindow, "Cannot create window", "Error", MB_OK);
		Last_Window = GreyWindow;
	}
	else
	{
		Last_Window->SetData(Window_Data);
  }
}


void TMyApp::InitMainWindow()
{
	time_t t;

    srand((unsigned) time(&t));
	MainWindow = new TMyWindow(NULL,"DIALOG_1", NULL);
}

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  LPSTR lpCmdLine, int nCmdShow)
{
	TMyApp MyApp("Continuous Mitochondrial Statistics", hInstance, hPrevInstance,
               lpCmdLine, nCmdShow);
  MyApp.Run();
  return MyApp.Status;
}
