/* :ts=8 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#include "general.h"
#include "globals.h"
#include "intui.h"
#include "timer.h"
#include "spl_math.h"
#include "spl_util.h"
#include "spl_gfx.h"
#include "pan.h"

static Boolean_T	Pan_Active;
static short		Old_X;
static short		Old_Y;
static Vector_T		Orig_Pos;
static Vector_T		Orig_Offset;
static Vector_T		Box_Min, Box_Max;

static
void Pan_Timeout()
/************************************************************************/
/*                                                                      */
/* Function called when timer expires: Draw all splines.		*/
/*                                                                      */
/************************************************************************/
{    
    Vector_T	New_Offset;
    Vector_T	Distance;
    Vector_T	Corrected_Pos;
	/* Convert Current_Pos the original offset 		*/
	/* and compute moved distance.				*/
	/* Subtract this from original offset to get new offset	*/
    Vec3Op(Corrected_Pos, =, Current_Pos, -, Offset);
    Vec2Op(Corrected_Pos, +=, Orig_Offset);

    Vec3Op(Distance, =, Corrected_Pos, -, Orig_Pos);

    Vec3Op(New_Offset, =, Orig_Offset, -, Distance);

    Set_Offset(New_Offset, Select_View_Id);

    Compute_Splines();
    Clear_All(What_All);
    Draw_All(What_All);

    Redraw_Mask = 0;

    Stop_Timer();

} /* Pan_Timeout */

static 
void Pan_Redraw(long Mask)
/************************************************************************/
/*                                                                      */
/* Function called to redraw screen while panning a view.		*/
/*                                                                      */
/************************************************************************/
{    
    Vector_T	New_Offset;
    Vector_T	Distance;
    Vector_T	Corrected_Pos;
	/* Convert Current_Pos the original offset 		*/
	/* and compute moved distance.				*/
	/* Subtract this from original offset to get new offset	*/
    Vec3Op(Corrected_Pos, =, Current_Pos, -, Offset);
    Vec2Op(Corrected_Pos, +=, Orig_Offset);

    Vec3Op(Distance, =, Corrected_Pos, -, Orig_Pos);

    Vec3Op(New_Offset, =, Orig_Offset, -, Distance);

    Set_Offset(New_Offset, Select_View_Id);

    Clear_All(What_All);
    Draw_Box(Box_Min, Box_Max, NULL, DM_Plane, What_All);
    Draw_Origin(DM_Normal, What_All);

    Start_Timer(Delay_Draw_Seconds, Delay_Draw_Micros);

    Redraw_Mask = 0;

} /* Pan_Redraw */

static
void Pan_Select_Up(short X, short Y)
/************************************************************************/
/*                                                                      */
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{
	/* If the timer hasn't expired, then call the timeout handler to*/
	/* compute and draw the splines.			 	*/

    if (!Check_Timer()) Pan_Timeout();

    Set_Mode_Normal();

} /* Pan_Select_Up */

static 
void Pan_Select_Down(short X, short Y)
/************************************************************************/
/*                                                                      */
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{
    Select_View_Id = Screen_To_World(X, Y, Current_Pos);
    if (Select_View_Id < 0) return;

    if (Get_Bounding_Box(Box_Min, Box_Max)) {
	Vec3Scalar(Box_Min, =, -Grid_Size, -Grid_Size, -Grid_Size);
	Vec3Scalar(Box_Max, =,  Grid_Size,  Grid_Size,  Grid_Size);

    }
    Draw_Box(Box_Min, Box_Max, NULL, DM_Plane, What_All);

    Vec2Op(Orig_Pos, =, Current_Pos);

    Old_X = X;
    Old_Y = Y;

    Pan_Active = TRUE;

} /* Pan_Select_Down */

static 
void  Pan_Move(short X, short Y)
/************************************************************************/
/*                                                                      */
/* Function called when mouse is moved to pan a view.			*/
/* X, Y are the actual coordinates in the active window.		*/
/*                                                                      */
/************************************************************************/
{
    short View_Id;

    if (!Pan_Active) return;

    View_Id = Screen_To_World(X, Y, Current_Pos);

    if (View_Id != Select_View_Id) return;

    if (Old_X == X && Old_Y == Y) return;

    Old_X = X;
    Old_Y = Y;

    if (Redraw_Always) Pan_Redraw(What_All);
    else               Redraw_Mask = What_All;

} /* Pan_Pan */

static
Boolean_T Pan_Handle_Event(struct IntuiMessage *Msg)
/************************************************************************/
/*                                                                      */
/* Event handler routine for the 'PAN VIEW' mode.			*/
/* Events handled:							*/
/*	Select down: Start pan.						*/
/*	Select up: Stop pan.						*/
/*	Mouse move: Change position.					*/
/*                                                                      */
/************************************************************************/
{

    switch (Msg->Class) {


    case IDCMP_MOUSEBUTTONS:
		/* Msg->Code contain id of button pressed 		*/
		/* Msg->MouseX and Msg->MouseY contain mouse position 			*/

	switch (Msg->Code) {

	case SELECTDOWN:
	    Pan_Select_Down(Msg->MouseX, Msg->MouseY);
	    return(TRUE);

	case SELECTUP:
	    Pan_Select_Up(Msg->MouseX, Msg->MouseY);
	    return(TRUE);

	} /* switch (Msg->Code) */
	break;

    case IDCMP_MOUSEMOVE:
	Pan_Move(Msg->MouseX, Msg->MouseY);
	return(TRUE);

    } /* switch (Msg->Class) */

    return(FALSE);

} /* Pan_Handle_Event */

void Set_Mode_Pan()
/************************************************************************/
/*                                                                      */
/* Start panning a view.						*/
/*                                                                      */
/************************************************************************/
{
    Pan_Active		= FALSE;
    State.Handle_Event	= Pan_Handle_Event;
    State.Timeout	= Pan_Timeout;
    State.Redraw	= Pan_Redraw;

    if (MQ_Size_Move_G > 0) {
        SetMouseQueue(Windows[Id_Active_Window].Window, MQ_Size_Move_G); 
        Redraw_Always = TRUE;
    } else Redraw_Always = FALSE;


    Vec2Op(Orig_Offset, =, Offset);

    sprintf(Error_Msg, "Pan view");
    Display_Status(Error_Msg);

} /* Set_Mode_Pan */
