/*
 * File:    demo.cc
 * Purpose: main application module, generated by wxBuilder.
 * Author:  Alejandro Aguilar-Sierra
 * Date:    June 1995
 * Description:
 * A demo for the wxIma class library
 */

// For compilers that support precompilation, includes "wx.h".
#include "wx_prec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx.h"
#endif

#include "wx_help.h"
#include "wxima.h"
#include "demo.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

wxIma* ima;
BOOL BLT_FLAG = TRUE;

// Declare an instance of the application: allows the program to start
AppClass theApp;

// Called to initialize the program
wxFrame *AppClass::OnInit(void)
{

  // Initialize all the top-level window members to NULL.
  frame = NULL;
  if (!ParseCommandLine())
	 return NULL;

  frame =
	 new FrameClass(NULL, "Image demo", 609, 6, 300, 300, wxSDI | wxDEFAULT_FRAME, "frame");

  return frame;
}

// Parses the command line
Bool AppClass::ParseCommandLine(void)
{
  return TRUE;
}

/*
Main frame
*/
FrameClass::FrameClass(wxFrame *parent, char *title, int x, int y, int width, int height, long style, char *name):
  wxFrame(parent, title, x, y, width, height, style, name)
{
  // Initialize child subwindow members.
  canvas = NULL;
  ima = NULL;

  CreateStatusLine(1);
  // Create a menu bar for the frame
  menuBar = new wxMenuBar;
  wxMenu *menu1 = new wxMenu;
  menu1->Append(FRAMECLASS_OPEN, "&Open", "Load an image");
  menu1->Append(FRAMECLASS_SAVE, "&Save", "Save the image");
  menu1->Append(FRAMECLASS_SAVE_AS, "S&ave as...");
  menu1->AppendSeparator();
  menu1->Append(FRAMECLASS_INFO, "&Info", "Info about the image");
  menu1->AppendSeparator();
  menu1->Append(FRAMECLASS_EXIT, "&Exit");
  menuBar->Append(menu1, "&File");
  wxMenu *menu2 = new wxMenu;
  menu2->Append(FRAMECLASS_DRAW, "&Draw");
  menu2->Append(FRAMECLASS_STRETCH, "&Stretch");
  menu2->AppendSeparator();
  menu2->Append(FRAMECLASS_SPHERE, "&Ellipse");
  menuBar->Append(menu2, "&Options");
  wxMenu *menu3 = new wxMenu;
  menu3->Append(FRAMECLASS_CONTENTS, "&Contents");
  menu3->Append(FRAMECLASS_ABOUT, "&About...");
  menuBar->Append(menu3, "&Help");
  SetMenuBar(menuBar);

  // Create child subwindows.
  canvas = new CanvasClass(this, 0, 0, 292, 238, wxRETAINED, "canvas");

  // Ensure the subwindows get resized o.k.
  OnSize(width, height);

  // Centre frame on the screen.
//  Centre(wxBOTH);

  // Show the frame.
  Show(TRUE);
}

FrameClass::~FrameClass(void)
{
}

Bool FrameClass::OnClose(void)
{
  // Clean up any associated data here.
  theApp.frame = NULL;
  return TRUE;
}

void FrameClass::OnSize(int w, int h)
{
  // Let default member handle sizing for only one subwindow.
  wxFrame::OnSize(w, h);
}

void FrameClass::OnMenuCommand(int commandId)
{
  switch (commandId)
  {
	 // Open
	 case FRAMECLASS_OPEN:
	 {
		// Show file selector.  
		char *f = wxFileSelector("Open Image", NULL, NULL,"bmp",
		  "PNG files (*.png)|*.png|JPEG files (*.jpg)|*.jpg|Bmp files (*.bmp)|*.bmp|Gif files (*.gif)|*.gif");

		if (!f)
		  return;

		if (ima) delete ima;
		wxBeginBusyCursor();
		ima = new wxIma(f);
		wxEndBusyCursor();
		if (!ima)
		  break;
		canvas->SetIma(ima);
		canvas->AdjustScrollBars();
//		canvas->Refresh();
		break;
	 }
	 // Save
	 case FRAMECLASS_SAVE:
	 {
	 }
	 // Save as...
	 case FRAMECLASS_SAVE_AS:
	 {
	 
		char *f = wxFileSelector("Save Image", NULL, ima->GetFilename(), NULL,
		  "PNG files (*.png)|*.png|JPEG files (*.jpg)|*.jpg|Bmp files (*.bmp)|*.bmp|Gif files (*.gif)|*.gif",
		wxSAVE | wxOVERWRITE_PROMPT);

		if (f) {
		  if (!ima->savefile(f))
			 wxMessageBox("Image couldn't be saved", "Warning");
		}

		break;
	 }
	 // Info
	 case FRAMECLASS_INFO:
	 {
		char sx[80];
		sprintf(sx,"Width = %d\nHeight = %d\nDepth = %d",
		ima->GetWidth(), ima->GetHeight(), ima->GetDepth());
		wxMessageBox(sx, "Image info");
		break;
	 }
	 // Exit
	 case FRAMECLASS_EXIT:
	 {     
		Show(FALSE);
		OnClose();
		delete this;
		theApp.frame = NULL;
		break;
	 }
	 // Draw
	 case FRAMECLASS_DRAW:
	 {
		BLT_FLAG = TRUE;
		menuBar->Enable(FRAMECLASS_DRAW, FALSE);
		menuBar->Enable(FRAMECLASS_STRETCH, TRUE);
		canvas->AdjustScrollBars();
		break;
	 }
	 // Stretch
	 case FRAMECLASS_STRETCH:
	 {
		BLT_FLAG = FALSE;
		menuBar->Enable(FRAMECLASS_DRAW, TRUE);
		menuBar->Enable(FRAMECLASS_STRETCH, FALSE);
		canvas->AdjustScrollBars();
		break;
	 }
	 // Sphere
	 case FRAMECLASS_SPHERE:
	 {
		ComputeNewIma();
		break;
	 }
	 // Contents
	 case FRAMECLASS_CONTENTS:
	 {
		break;
	 }
	 // About...
	 case FRAMECLASS_ABOUT:
	 {
		(void)wxMessageBox("wxIma 0.1\nAuthor: Alejandro Aguilar Sierra\nCCA UNAM (c) 1995",
				"About");
		break;
	 }
  default:
	 break;
  }
}

CanvasClass::CanvasClass(wxFrame *parent, int x, int y, int width, int height, long style, char *name):
  wxCanvas(parent, x, y, width, height, style, name)
{
  //	AdjustScrollBars();
  ima = 0;
}

CanvasClass::~CanvasClass(void)
{
}

// Called when canvas is resized.
void CanvasClass::OnSize(int w, int h)
{
  wxCanvas::OnSize(w, h);
}

// Called when canvas needs to be repainted.
void CanvasClass::OnPaint(void)
{
  // Speeds up drawing under Windows.
  GetDC()->BeginDrawing();

  if (ima) {
	 if (BLT_FLAG)
		ima->Draw(GetDC(), 0, 0, ima->GetWidth(), ima->GetHeight());
	 else {
		int w, h;
		GetSize(&w, &h);
		ima->Stretch(GetDC(), 0, 0, w, h);
	 }
  }

  GetDC()->EndDrawing();
}

// Called when the canvas receives a key event.
void CanvasClass::OnChar(wxKeyEvent& event)
{
  wxCanvas::OnChar(event);
}


// Called when the canvas receives a mouse event.
void CanvasClass::OnEvent(wxMouseEvent& event)
{
  wxCanvas::OnEvent(event);

  if (!ima) return;

  if (event.LeftUp()) {
	 char s[80];
	 byte r = 0, g = 0, b = 0;
	 float x, y;

	 event.Position(&x, &y);
	 if (!BLT_FLAG)
	 {
		int w, h;
		GetClientSize(&w, &h);
		x *= ima->GetWidth()/(float)w;
		y *= ima->GetHeight()/(float)h;
	 }
	 if (ima->Inside((int)x, (int)y)) {
		sprintf(s,"X = %.0f Y = %.0f  Idx=%d", x, y, ima->GetIndex((int)x, (int)(ima->GetHeight() - y)));
		if (ima->GetRGB((int)x, (int)(ima->GetHeight() - y), &r, &g, &b))
		  sprintf(&s[strlen(s)],"  RGB = (%d, %d, %d)", r, g, b);
	 } else strcpy(s," ");

	 ((FrameClass *)GetParent())->SetStatusText(s);
  }
}

void CanvasClass::AdjustScrollBars(void)
{
 if (ima && BLT_FLAG) {
	 SetScrollbars(20, 20, ima->GetWidth()/20,
		  ima->GetHeight()/20, 10, 10);
	 if (ima->GetColourMap())
		SetColourMap(ima->GetColourMap());
  }
  else
	  EnableScrolling(FALSE, FALSE);
  Refresh();
}


#define EPSILON (0.0000001)

int ComputePixel(float x, float y, float &x1, float &y1)
{
  float r, nn;

  if (x==0 && y==0) {
	 x1 = x;
	 y1 = y;
	 return 1;
  }

  nn = sqrt(x*x + y*y);
  r = (fabs(x) > fabs(y)) ? fabs(nn/x): fabs(nn/y);

  x1 = (r*x);
  y1 = (r*y);

  return 1;
}

void FrameClass::ComputeNewIma(void){
  int x, y, x1, y1;
  float fx, fy, xmid, ymid, ar;
  wbIma* ima2 = new wbIma(ima);

  xmid = ima->GetWidth()/2.;
  ymid = ima->GetHeight()/2.;
  ar = (float)(ima->GetHeight())/(float)(ima->GetWidth());
  wxBeginBusyCursor();
  for (y=0; y<ima->GetHeight(); y++) {
	 for (x=0; x<ima->GetWidth(); x++) {
		ComputePixel(ar*(x-xmid), y-ymid, fx, fy);
		x1 = (int)(xmid+fx/ar);
		y1 = (int)(ymid+fy);
		if (ima->Inside(x1, y1))
		  ima2->SetIndex(x, y, ima->GetIndex(x1, y1));
		else
		  ima2->SetIndex(x, y, 0);
	 }
  }
  wxEndBusyCursor();
//  delete ima;
//  ima = (wxIma*)ima2;
  canvas->SetIma(ima2);
  canvas->Refresh();
}
