#include <Global/Main_Global.h>

SAVEDS ULONG _New(struct IClass *cl,Object *obj,Msg msg)
{
        struct Instance *Data;
        struct Point *Point1;
        struct Point *Point2;
        struct Point *Point3;
        
        if (!(obj = (Object *)DoSuperMethodA(cl,obj,msg)))
                return(0);
                      
        Data = INST_DATA(cl,obj);
        
        Data->Points = malloc(sizeof(struct List));             //Allocate Size of List
        NewList(Data->Points);					// List To Store All Points
        
        Point1 = malloc(sizeof(struct Point));
        Point2 = malloc(sizeof(struct Point));
        Point3 = malloc(sizeof(struct Point));
        
        Data->Middley=NULL;
        Data->Middlex=NULL;
        Data->LastMiddlex=NULL;
        Data->LastMiddley=NULL;
              
        Data->StartFrame = GetTagData(MUIA_Envelope_StartFrame,     1,  ((struct opSet *)msg)->ops_AttrList);
        Data->EndFrame   = GetTagData(MUIA_Envelope_EndFrame,      50,  ((struct opSet *)msg)->ops_AttrList);
        Data->MaxValue   = GetTagData(MUIA_Envelope_LargestValue, 100,  ((struct opSet *)msg)->ops_AttrList);
        Data->MinValue   = GetTagData(MUIA_Envelope_SmallestValue,  0,  ((struct opSet *)msg)->ops_AttrList);
        
        Point1->Frame_Number = Data->StartFrame;
        Point1->Value = (Data->MaxValue-Data->MinValue)/2;   
        Point1->Converted=FALSE;
        Point1->Selected=FALSE;
        
        Point2->Frame_Number = 30;
        Point2->Value = 60;
        Point2->Converted=FALSE;
        Point2->Selected=FALSE;
        
        Point3->Frame_Number = Data->EndFrame;
        Point3->Value = (Data->MaxValue-Data->MinValue)/2;
        Point3->Converted=FALSE;
        Point3->Selected=FALSE;
       
        AddTail(Data->Points,Point1);
        AddTail(Data->Points,Point2);
        AddTail(Data->Points,Point3);
  
        return((ULONG)obj);
}

__saveds ULONG _Dispose(struct IClass *cl,Object *obj,Msg msg)
{
        struct Instance *Data = INST_DATA(cl,obj);
        free(Data->Points);
        
        return(DoSuperMethodA(cl,obj,msg));
}         
/*********************************Setup/Cleanup IDCMP Requests****************************/

__saveds ULONG _Setup(struct IClass *cl,Object *obj,Msg msg)
{
        if (!(DoSuperMethodA(cl,obj,msg)))
                return(FALSE);

        MUI_RequestIDCMP(obj,IDCMP_MOUSEBUTTONS);
       
        return(TRUE);
}

__saveds ULONG _Cleanup(struct IClass *cl,Object *obj,Msg msg)
{
        MUI_RejectIDCMP(obj,IDCMP_MOUSEBUTTONS);
        
        return(DoSuperMethodA(cl,obj,msg));
}

/********************************Show/Hide RasterPort Information ***********************/

__saveds ULONG _Show(struct IClass *cl,Object *obj,Msg msg)
{
        struct Instance *Data = INST_DATA(cl,obj);
        
        /* Part 1: */
        struct Point *SpareNode;
        float StartFrame=       Data->StartFrame;
        float EndFrame  =       Data->EndFrame;
        float MinValue  =       Data->MinValue;
        float MaxValue  =       Data->MaxValue;
        float MiddleFrame;
        float MiddleValue;
       
        float Virtx,Virty;
        
        

        if (!(DoSuperMethodA(cl,obj,msg)))
                return(FALSE);
                
        // Set Middle Points Since We Now Know The Dimentions of Raster
        Data->Middlex = ((_mright(obj)-_mleft(obj))/2)+_mleft(obj);
        Data->Middley = ((_mbottom(obj)-_mtop(obj))/2)+_mtop(obj);
        Data->FrameRes =  (_mright(obj)-_mleft(obj))/(EndFrame-StartFrame); 
        Data->ValueRes =  (_mbottom(obj)-_mtop(obj))/(MaxValue-MinValue);
        
        /* Non Working Scaling Code */
        // if((Data->LastMiddley)&&(Data->LastMiddlex))  
        //         {      
        //           Data->XScale = Data->Middlex/Data->LastMiddlex;
        //           Data->YScale = Data->Middley/Data->LastMiddley;
        //          }
                  
        for(SpareNode   =   Data->Points->lh_Head;   
            SpareNode->ln_Succ;   
            SpareNode   =   SpareNode->ln_Succ) 
           { 
              if(!SpareNode->Converted) 
                 { 
                  // Convert New Raws To Cords
                  MiddleFrame = ((EndFrame-StartFrame)/2)+StartFrame;
                  MiddleValue = ((MaxValue-MinValue)/2)+MinValue;   
                  Virtx = (Data->FrameRes*SpareNode->Frame_Number)+_mleft(obj);
                  Virty = (Data->ValueRes*SpareNode->Value)+_mtop(obj);
                  SpareNode->x = (Virtx-Data->Middlex);
                  SpareNode->y = (Virty-Data->Middley);
                  SpareNode->Converted = TRUE; 
                 
                 } 
                  /* Non Working Scaling Code */
                  // SpareNode->x = SpareNode->x*Data->XScale;
                  // SpareNode->y = SpareNode->y*Data->YScale;           
             
            }
        /* Non Working Scaling Code */
        // Data->LastMiddlex = Data->Middlex;        
        // Data->LastMiddley = Data->Middley;            
       
       
    return(TRUE);
}

__saveds ULONG _Hide(struct IClass *cl,Object *obj,Msg msg)
{
        return(DoSuperMethodA(cl,obj,msg));
}

/*******************************AskMinMax Rendering Sizes *****************************/

__saveds ULONG _AskMinMax(struct IClass *cl,Object *obj,struct MUIP_AskMinMax *msg)
{
        
        DoSuperMethodA(cl,obj,msg);
        msg->MinMaxInfo->MinWidth  += 100;
        msg->MinMaxInfo->DefWidth  += 120;
        msg->MinMaxInfo->MaxWidth  += 500;
        msg->MinMaxInfo->MinHeight += 40;
        msg->MinMaxInfo->DefHeight += 90;
        msg->MinMaxInfo->MaxHeight += 300;
        return(0);
}

/*******************************HandleInput Input Handler *****************************/

__saveds ULONG _HandleInput(struct IClass *cl,Object *obj,struct MUIP_HandleInput *msg)
{

        struct Instance *Data = INST_DATA(cl,obj);
        struct Point *SpareNode;
        ULONG Flags;
        BOOL Removed=FALSE;
        int counter=1;
        float Virtx,Virty;
        int chaz,dave,chazplus,daveplus;

        if(msg->imsg)
        {
         switch(msg->imsg->Class)
              { 
               case IDCMP_MOUSEBUTTONS:
                 { 
                                    
                  switch(msg->imsg->Code)
                     {
                      case SELECTDOWN:                       
                        if(_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
                           {                                           
	                    for(SpareNode = Data->Points->lh_Head;
        	                SpareNode->ln_Succ;
                	        SpareNode = SpareNode->ln_Succ)
                       	       {	    
	                  	if( ( (msg->imsg->MouseX>=xpoint(SpareNode->x,Data)-2)  && 
        	               	    (msg->imsg->MouseX<=xpoint(SpareNode->x,Data)+2) ) &&
                	       	    ( (msg->imsg->MouseY>=ypoint(SpareNode->y,Data)-2)  && 
                        	    (msg->imsg->MouseY<=ypoint(SpareNode->y,Data)+2) ) )
                              	   { 
                               	    SpareNode->Selected=TRUE;
                               	    MUI_RequestIDCMP(obj,IDCMP_MOUSEMOVE);
                                    break;
                                   }                 
                               }                 
                           }
                         break;
                         
                      case SELECTUP:
                        for(SpareNode = Data->Points->lh_Head;
                            SpareNode->ln_Succ;
                            SpareNode = SpareNode->ln_Succ)
                           {
                            if(SpareNode->Selected)
                              {
                                SpareNode->Selected=FALSE;
                                MUI_RejectIDCMP(obj,IDCMP_MOUSEMOVE);
                               }
                           }
                         MUI_Redraw(obj,MADF_DRAWOBJECT);       
                       break;
                        
                        
                      case MENUUP:
                        Removed=FALSE;
                       	for(SpareNode = Data->Points->lh_Head;
        	            SpareNode->ln_Succ;
                	    SpareNode = SpareNode->ln_Succ)
                           {	    
	                	if( ( (msg->imsg->MouseX>=xpoint(SpareNode->x,Data)-2)  && 
        	               	    (msg->imsg->MouseX<=xpoint(SpareNode->x,Data)+2) ) &&
                	       	    ( (msg->imsg->MouseY>=ypoint(SpareNode->y,Data)-2)  && 
                      	      	    (msg->imsg->MouseY<=ypoint(SpareNode->y,Data)+2) ) )
                               	   {
                               	    
                               	    if((SpareNode!=Data->Points->lh_Head)&(SpareNode!=Data->Points->lh_TailPred))
                      	                 {
                       	                  Remove(SpareNode);
                       	                  free(SpareNode);
                       	                  Removed=TRUE;
                       	                  break; 
                       	                 }
                       	                 else
                       	                  DisplayBeep(0);
                               	  }
                           }
                               	 if(!Removed)
                               	  
                               	   DoMethod(obj,MUIM_Envelope_AddPoint,xpoint_(msg->imsg->MouseX,Data),ypoint_(msg->imsg->MouseY,Data));
                                  
                                  
                         
                            
                            MUI_Redraw(obj,MADF_DRAWOBJECT);
                        break;
                        
                      
                        
                   } 
                   }
                         
                               
                      


                  case IDCMP_MOUSEMOVE:
                        {
                         if (_isinobject(msg->imsg->MouseX,msg->imsg->MouseY))
                             {
                               for(SpareNode = Data->Points->lh_Head;
                                   SpareNode->ln_Succ;
                                   SpareNode = SpareNode->ln_Succ)
                                   {
                                    if(SpareNode->Selected)
                                       {
                                        SpareNode->x = xpoint_(msg->imsg->MouseX,Data);
                                        SpareNode->y = ypoint_(msg->imsg->MouseY,Data);
                                        
                                        if(SpareNode==Data->Points->lh_Head)
                                            SpareNode->x = Data->Middlex-_mright(obj);
                                           
                                        if(SpareNode==Data->Points->lh_TailPred)
                                           SpareNode->x = Data->Middlex-_mleft(obj);                                        
                                       }
                                   }    
                               MUI_Redraw(obj,MADF_DRAWUPDATE);
                             }
                         }
                  break;
                }
        }

        return(0);
}

int xpoint(  int  Realx,struct Instance *Data)
{
 float Real;
 int result;
 Real = Realx;
 result = Realx+Data->Middlex;
 return(result);
}
int ypoint(  int  Realy,struct Instance *Data)
{
 float Real;
 int result;
 Real = Realy;
 result = Realy+Data->Middley;
 return(result);
}

int xpoint_(  int  Realx,struct Instance *Data)
{
 float Real;
 int result;
 Real = Realx;
 result = Realx-Data->Middlex;
 return(result);
}
int ypoint_(  int  Realy,struct Instance *Data)
{
 float Real;
 int result;
 Real = Realy;
 result = Realy-Data->Middley;
 return(result);
}

SAVEDS ULONG _Draw(struct IClass *cl,Object *obj,struct MUIP_Draw *msg)
{
        struct Instance *Data = INST_DATA(cl,obj);
        struct Point *Spare;
        struct Point *SpareNode;
        BOOL First=TRUE;
        BOOL UFirst=TRUE;
        BOOL Update;
        int conversion;
        int Counter = 0;
        float HRate;
        int chaz,dave;
        float MBottom,MTop;
        
        DoSuperMethodA(cl,obj,msg);
        
        if(msg->flags & MADF_DRAWUPDATE)
          {
            Spare = Data->Points->lh_Head;
           Move(_rp(obj),xpoint(Spare->x,Data),ypoint(Spare->y,Data));
           
           for(SpareNode = Data->Points->lh_Head;
               SpareNode->ln_Succ;
               SpareNode = SpareNode->ln_Succ)
               {
               
                if(_isinobject(xpoint(SpareNode->x,Data),ypoint(SpareNode->y,Data)))
                   {
                   SetDrMd(_rp(obj),COMPLEMENT);
                   if(SpareNode->Lasty&&SpareNode->Lastx)
                       {
                         SetAPen(_rp(obj),_dri(obj)->dri_Pens[BACKGROUNDPEN]);
                         DrawEllipse(_rp(obj),SpareNode->Lastx,SpareNode->Lasty,2,2);
                        }
                    SetAPen(_rp(obj),_dri(obj)->dri_Pens[TEXTPEN]);
                    DrawEllipse(_rp(obj),xpoint(SpareNode->x,Data),ypoint(SpareNode->y,Data),2,2);
                    SpareNode->Lastx = xpoint(SpareNode->x,Data);
                    SpareNode->Lasty = ypoint(SpareNode->y,Data);
                    SetDrMd(_rp(obj),JAM1);  
                   }
                   
               }
           }
           else
        if(msg->flags & MADF_DRAWOBJECT)
           
          {
          SetAPen(_rp(obj),_dri(obj)->dri_Pens[SHINEPEN]);
           Move(_rp(obj),_left(obj),_bottom(obj)+(_top(obj)-_bottom(obj))/2);
           Draw(_rp(obj),_right(obj),_bottom(obj)+(_top(obj)-_bottom(obj))/2);
           Move(_rp(obj),_left(obj)+(_right(obj)-_left(obj))/2,_top(obj));
           Draw(_rp(obj),_left(obj)+(_right(obj)-_left(obj))/2,_bottom(obj));
           Spare = Data->Points->lh_Head;
           Move(_rp(obj),xpoint(Spare->x,Data),ypoint(Spare->y,Data));
           
           for(SpareNode = Data->Points->lh_Head;
               SpareNode->ln_Succ;
               SpareNode = SpareNode->ln_Succ)
               {
                if(!First)
                 Draw(_rp(obj),xpoint(SpareNode->x,Data),ypoint(SpareNode->y,Data));
                 
                if(_isinobject(xpoint(SpareNode->x,Data),ypoint(SpareNode->y,Data)))
                   {
                    if(SpareNode->Lasty&&SpareNode->Lastx)
                       {
                         SetAPen(_rp(obj),_dri(obj)->dri_Pens[BACKGROUNDPEN]);
                         DrawEllipse(_rp(obj),SpareNode->Lastx,SpareNode->Lasty,2,2);
                         SetAPen(_rp(obj),_dri(obj)->dri_Pens[TEXTPEN]);
                        }
                    SetAPen(_rp(obj),_dri(obj)->dri_Pens[TEXTPEN]);
                    DrawEllipse(_rp(obj),xpoint(SpareNode->x,Data),ypoint(SpareNode->y,Data),2,2);
                    SpareNode->Lastx = xpoint(SpareNode->x,Data);
                    SpareNode->Lasty = ypoint(SpareNode->y,Data);
                   }
                 First=FALSE;
               }
               }
        return(0);
}




SAVEDS ASM ULONG MyDispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
{
        switch (msg->MethodID)
        {
                case OM_NEW          : return(_New      (cl,obj,(APTR)msg));
                case OM_DISPOSE      : return(_Dispose  (cl,obj,(APTR)msg));
                case OM_SET          : return(_Set      (cl,obj,(APTR) msg));
                case OM_GET          : return(_Get      (cl,obj,(APTR) msg));
                case MUIM_AskMinMax  : return(_AskMinMax  (cl,obj,(APTR)msg));
                case MUIM_Draw       : return(_Draw       (cl,obj,(APTR)msg));
                case MUIM_Show       : return(_Show       (cl,obj,(APTR)msg));
                case MUIM_Hide       : return(_Hide       (cl,obj,(APTR)msg));
                case MUIM_HandleInput: return(_HandleInput(cl,obj,(APTR)msg));
                case MUIM_Setup      : return(_Setup      (cl,obj,(APTR)msg));
                case MUIM_Cleanup    : return(_Cleanup    (cl,obj,(APTR)msg));
                case MUIM_Envelope_AddPoint : return(_AddPoint   (cl,obj,(APTR)msg));
        }

        return(DoSuperMethodA(cl,obj,msg));
}

