#include <stdio.h>
#include <stdlib.h>

#include <exec/types.h>
#include <graphics/modeid.h>
#include <devices/timer.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <exec/memory.h>

#include "/Shared/SH_view.h"
#include "/Shared/SH_timer.h"
#include "/Shared/SH_sequence.h"
#include "/music/music_play.h"
#include "/data/incbiny.h"
#include "/tools.h"
#include "TM_structures.h"
#include "TM_render.h"
#include "TM_animation.h"
#include "TM_sequence.h"
#include "TM_reader.h"
#include "/BumpMapping/BM_Render.h"
#include "/BumpMapping/BM_Precalc.h"

ANIM_COMMAND VAExitList[] =
{
	{ AC_FADE_TO_WHITE, NULL },
	{ AC_OBJECT, 0 },
	{ AC_SETPOSX, 0 },
	{ AC_SETPOSY, 0 },
	{ AC_SETPOSZ, 400 },
	{ AC_SETROTX, 0 },
	{ AC_SETROTY, 0 },
	{ AC_SETROTZ, 0 },
	{ AC_MOVEZ , -20},
	{ AC_DO, 2.5*SEC },
	{ AC_QUIT, 0 }
};


typedef struct Bulbs
          {
          LONG PosX,PosY;
          LONG Speed;
          LONG x,dx;
          }BULBS;

#define MAX_BULBS 6
#define RESX_BULB 60
#define RESY_BULB 15
#define SPEED_BULB 13

ULONG WhitePal[1000];

BULBS Bulbs[MAX_BULBS];

IMPORT TIMER *Timer;

UBYTE *EM_Back=NULL;

extern UBYTE EndChunky[320*TEXT_WIDTH];

extern UBYTE *Textures[2];
extern UBYTE *EnvMaps[2];

#define SEC2 (SEC/2)
#define SEC5 (SEC/13)

extern DVIEW *DView;
BOOL NewBulb = TRUE;
BOOL Mouse = FALSE;

LONG AnimTime = 0;
#define MAGIC_NUMBER 45000

LONG EM_RenderFrame(DVIEW *DView, SCENE *Scene)
{
FACE *tmpFace;
LONG VisibleFacesNumber;
LONG i;

	TM_TransformScene(Scene);
	VisibleFacesNumber = TM_CreateDepthBuffer(Scene, Scene->DeptBuffor);
	TM_SortDepthBuffer(Scene->DeptBuffor, VisibleFacesNumber);

     ClearChunky(DView);

	for(i=0; i<VisibleFacesNumber; i++)
	{
		tmpFace = Scene->DeptBuffor[i];

		RenderFace(tmpFace);
	}

	SafeRender(DView);
     DView->C2P(DView);
     RenderInfoBar(DView->RenderRP, 255);
	FrameEvent();
	SwitchView(DView);

	return IAL_OK;
}


LONG EXP_Sequence(UBYTE *Obj,ANIM_COMMAND *AnimLista,UWORD *Env)
{
SCENE *Scene,*Scene1;
LONG i,j,tmp;
OBJECT *Objects;
LONG dx,dy,dz,kk;	
ULONG *Pal = (LONG *)AnimLista[0].Parameter;

	if((Scene1 = EM_RelocScene(Obj)) == NULL) return 1L;

     Scene = RelocExplodeScene(Scene1);
     EM_FreeScene(Scene1);
     if(Scene==NULL) return 1L;

     Objects = Scene->Objects;

     EnvMapPtr = &Env[256*128];

	for(i=0; i<Scene->ONumber; i++)
		SetObjectFlags(&Scene->Objects[i],
									 OF_NEWPOS | OF_DISPLAY | OF_ENVIRONMENT,
									 FF_ENVIRONMENT);

	TM_DoAnim(DView, Scene, AnimLista, EM_RenderFrame);

     Objects[0].Flags &= (~OF_DISPLAY);

     for(j=1; j<Scene->ONumber; j++) Objects[j].Flags |= OF_NEWPOS;
     EM_RenderFrame(DView,Scene);

     Pal[0] = 0x01000001;

     FadeOutPalette(DView,Pal,0xffffffff,0xffffffff,0xffffffff,SEC5);
     StartMusic(Module);
     FadeInPalette(DView,Pal,0xffffffff,0xffffffff,0xffffffff,SEC5);
     while(P61_WaitPos2(0,59));
     FadeOutPalette(DView,Pal,0xffffffff,0xffffffff,0xffffffff,SEC5);
     FadeInPalette(DView,Pal,0xffffffff,0xffffffff,0xffffffff,SEC5);
     while(P61_WaitPos2(1,59));

		for(tmp=0;tmp<48;tmp++)
     {
      for(j=0;j<Scene->ONumber;j++)
      {
       for(kk=0;kk<Objects[j].FNumber;kk++)
       {     
       dx = Objects[j].Faces[kk].DPosX;
       dy = Objects[j].Faces[kk].DPosY;
       dz = Objects[j].Faces[kk].DPosZ;
       Objects[j].Faces[kk].V1->x += dx;
       Objects[j].Faces[kk].V2->x += dx;
       Objects[j].Faces[kk].V3->x += dx;
       Objects[j].Faces[kk].V1->y += dy;
       Objects[j].Faces[kk].V2->y += dy;
       Objects[j].Faces[kk].V3->y += dy;
       Objects[j].Faces[kk].V1->z += dz;
       Objects[j].Faces[kk].V2->z += dz;
       Objects[j].Faces[kk].V3->z += dz;
       }
      }
	 for(j=1; j<Scene->ONumber; j++) Objects[j].Flags |= OF_NEWPOS;
      EM_RenderFrame(DView,Scene);
     }


     Objects[0].Flags |= OF_DISPLAY | OF_NEWPOS;
     for(j=1; j<Scene->ONumber; j++) Objects[j].Flags &= (~OF_NEWPOS);
     for(j=1; j<Scene->ONumber; j++) Objects[j].Flags &= (~OF_DISPLAY);

     Pal[0] = 0x01000000;
     Objects[0].PosZ = 400;
     for(i=0;i<256*3;i++) WhitePal[1+i]=0xffffffff;
     WhitePal[0] = 0x01000000;
     LoadRGB32(DView->VP,WhitePal);
     EM_RenderFrame(DView,Scene);
     FadeInPalette(DView,Pal,0xffffffff,0xffffffff,0xffffffff,SEC5);

     for(i=0;i<48;i++)
     {
       for(kk=0;kk<Objects[0].FNumber;kk++)
       {     
       dx = Objects[0].Faces[kk].DPosX;
       dy = Objects[0].Faces[kk].DPosY;
       dz = Objects[0].Faces[kk].DPosZ;
       Objects[0].Faces[kk].V1->x -= dx;
       Objects[0].Faces[kk].V2->x -= dx;
       Objects[0].Faces[kk].V3->x -= dx;
       Objects[0].Faces[kk].V1->y -= dy;
       Objects[0].Faces[kk].V2->y -= dy;
       Objects[0].Faces[kk].V3->y -= dy;
       Objects[0].Faces[kk].V1->z -= dz;
       Objects[0].Faces[kk].V2->z -= dz;
       Objects[0].Faces[kk].V3->z -= dz;
       }
	 Objects[0].Flags |= OF_NEWPOS;
      EM_RenderFrame(DView,Scene);
     }

		tmp = 50;
    while(--tmp) WaitTOF();

     Pal[0] = 0x01000000;
     VAExitList[0].Parameter = (LONG)Pal;
    	TM_DoAnim(DView, Scene, VAExitList, EM_RenderFrame);

	EM_FreeScene(Scene);

	return SEQ_OK;
}

//--------------------------------------------------------------------
LONG FISH_RenderFrame(DVIEW *DView, SCENE *Scene)
{
FACE *tmpFace;
LONG VisibleFacesNumber;
LONG i,j;
LONG x,y,z;
LONG VNumber;
OBJECT *Objects = Scene->Objects;
LONG CurrentFrame = Scene->CurrentFrame+1;
LONG FrameTime;

		FrameTime = GetCurrentXTime();

	if(AnimTime > MAGIC_NUMBER)
	{
     VNumber = Scene->Objects[0].VNumber;
     for(i=0;i<VNumber;i++)
     {
          x = Objects[0].Vertices[(CurrentFrame*VNumber)+i].x;
          y = Objects[0].Vertices[(CurrentFrame*VNumber)+i].y;
          z = Objects[0].Vertices[(CurrentFrame*VNumber)+i].z;
          Objects[0].Vertices[i].x = x;
          Objects[0].Vertices[i].y = y;
          Objects[0].Vertices[i].z = z;
     }

     Scene->CurrentFrame += 1;
     if((Scene->CurrentFrame+1)== Scene->FramesNumber) Scene->CurrentFrame = 0;
   AnimTime = 0;
  }

	TM_TransformScene(Scene);
	VisibleFacesNumber = TM_CreateDepthBuffer(Scene, Scene->DeptBuffor);
	TM_SortDepthBuffer(Scene->DeptBuffor, VisibleFacesNumber);

     ClearBack(DView->Chunky,EM_Back);

	for(i=0; i<VisibleFacesNumber; i++)
	{
		tmpFace = Scene->DeptBuffor[i];

		RenderFace(tmpFace);
	}

     if(NewBulb)
     {
          x = (rand() % 305);
          for(i=0;i<MAX_BULBS;i++)
          {
               Bulbs[i].PosX = x + (rand() % RESX_BULB);
               Bulbs[i].PosY = 199 + (rand() % RESY_BULB);
							 if(Bulbs[i].PosX > 305) Bulbs[i].PosX = 305;
							 if(Bulbs[i].PosX < 0) Bulbs[i].PosX = 0;
               Bulbs[i].Speed = (rand() % SPEED_BULB) + 5;
               j = (rand() % 2) - 1;
               Bulbs[i].x = j;
               switch (j)
               {
                    case -1: Bulbs[i].dx = 1;break;
                    case  1: Bulbs[i].dx = -1;break;
                    case  0: Bulbs[i].dx = 1;break;
                    default: break;
              }
          }
       NewBulb = FALSE;
     }
     else
     {
          for(i=0;i<MAX_BULBS;i++)
          {
               Bulbs[i].PosY -= Bulbs[i].Speed;
               if((Bulbs[i].PosY < 188) && (Bulbs[i].PosY > -1))
                  PutBulb(FishBulb,DView->Chunky,Bulbs[i].PosX+Bulbs[i].x,Bulbs[i].PosY);

               Bulbs[i].x += Bulbs[i].dx;
               j = Bulbs[i].x;
               switch (j)
               {
                    case -1: Bulbs[i].dx = 1;break;
                    case  1: Bulbs[i].dx = -1;break;
                    case  0: Bulbs[i].dx = 1;break;
                    default: break;
               }
               
               
          }          
          y = 0;
          for(i=0;i<MAX_BULBS;i++)
               if(Bulbs[i].PosY > -1) y+=1;

          if(y == 0) NewBulb = TRUE;
     }

	SafeRender(DView);
     DView->C2P(DView);
     RenderInfoBar(DView->RenderRP, 12);
	FrameEvent();
	SwitchView(DView);

  AnimTime += (GetCurrentXTime() - FrameTime);

	return IAL_OK;
}


LONG FISH_Sequence(UBYTE *Obj,ANIM_COMMAND *AnimLista,UBYTE *Texture,UBYTE *Back)
{
SCENE *Scene;
LONG i;

     i = (LONG)Timer->TimeIO;
     srand(i);

	if((Scene = RellocAnimScene(Obj)) == NULL) return 1L;

     TxtMapPtr = &Texture[256*128];
     EM_Back=Back;

	for(i=0; i<Scene->ONumber; i++)
		SetObjectFlags(&Scene->Objects[i],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE);

	TM_DoAnim(DView, Scene, AnimLista, FISH_RenderFrame);

	EM_FreeScene(Scene);

	return SEQ_OK;
}

//--------------------------------------------------------------------
LONG NERA_Sequence(UBYTE *Obj,ANIM_COMMAND *AnimLista,UWORD *Env,UBYTE *Back,WORD *Bump,UBYTE *Shine, UBYTE *Txt)
{
SCENE *Scene;
LONG i;

	   if((Scene = EM_RelocScene(Obj)) == NULL) return 1L;

     EM_Back=Back;
			TxtMapPtr = &Txt[256*128];
			EnvMapPtr = &Env[256*128];
			BumpMapPtr = &Bump[256*128];
 			ShineLUTPtr = Shine;

	for(i=0; i<Scene->ONumber; i++)
		SetObjectFlags(&Scene->Objects[i],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE | OF_ENVIRONMENT | OF_BUMP,
									 FF_TEXTURE | FF_ENVIRONMENT | FF_BUMP);

	TM_DoAnim(DView, Scene, AnimLista, NERA_RenderFrame);

	EM_FreeScene(Scene);

	return SEQ_OK;
}

LONG NERA_RenderFrame(DVIEW *DView, SCENE *Scene)
{
LONG VisibleFacesNumber,i;
FACE *tmpFace;

  ClearBack(DView->Chunky,EM_Back);
	TM_TransformScene(Scene);
	VisibleFacesNumber = TM_CreateDepthBuffer(Scene, Scene->DeptBuffor);
	TM_SortDepthBuffer(Scene->DeptBuffor, VisibleFacesNumber);

	for(i=0; i<VisibleFacesNumber; i++)
	{
		tmpFace = Scene->DeptBuffor[i];

		RenderFace(tmpFace);
	}

	SafeRender(DView);
	DView->C2P(DView);
     RenderInfoBar(DView->RenderRP, 255);
	FrameEvent();
	SwitchView(DView);
	return IAL_OK;
}

//--------------------------------------------------------------------
LONG CLMN_Sequence(UBYTE *Obj,ANIM_COMMAND *AnimLista,ANIM_COMMAND *EndAnimLista)
{
SCENE *Scene;
LONG state;

	if((Scene = EM_RelocScene(Obj)) == NULL) return 1L;

/*
Object: out (0)
Object: COLM0_04 93/79/6 (1)
Object: COLM0_04 93/79/6 (2)
Object: COLM0_04 93/79/6 (3)
Object: out-1 (4)
*/

		SetObjectFlags(&Scene->Objects[0],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE);
		SetObjectFlags(&Scene->Objects[1],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE);
		SetObjectFlags(&Scene->Objects[2],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE);
		SetObjectFlags(&Scene->Objects[3],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE);
		SetObjectFlags(&Scene->Objects[4],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE,
									 FF_TEXTURE|(1L<<16));

	TM_DoAnim(DView, Scene, AnimLista, CLMN_RenderFrame);

  Mouse = TRUE;

	do
  {  
   state = TM_DoAnim(DView, Scene, EndAnimLista, CLMN_RenderFrame);
  }while(state == DA_NORMAL_TERMINATION);

	EM_FreeScene(Scene);

	return SEQ_OK;
}

LONG CLMN_RenderFrame(DVIEW *DView, SCENE *Scene)
{
FACE *tmpFace;
LONG VisibleFacesNumber;
LONG i;
LONG TM;

	TM_TransformScene(Scene);
	VisibleFacesNumber = TM_CreateDepthBuffer(Scene, Scene->DeptBuffor);
	TM_SortDepthBuffer(Scene->DeptBuffor, VisibleFacesNumber);

  ClearChunky(DView);
//	TM_RenderBackground(Scene->Objects[0].RotY<<1, -Scene->Objects[0].RotX,  DView, Textures[2]);

	for(i=0; i<VisibleFacesNumber; i++)
	{
		tmpFace = Scene->DeptBuffor[i];
          TM = (tmpFace->Flags & 0x00ff0000) >> 16;
          TxtMapPtr = Textures[TM];

		tmpFace->V1->u = tmpFace->u1;
		tmpFace->V1->v = tmpFace->v1;
		tmpFace->V2->u = tmpFace->u2;
		tmpFace->V2->v = tmpFace->v2;
		tmpFace->V3->u = tmpFace->u3;
		tmpFace->V3->v = tmpFace->v3;
		RenderFace(tmpFace);
	}

 if(Mouse)
   PutText(EndChunky,DView->Chunky,77,TEXT_WIDTH);

	SafeRender(DView);
	DView->C2P(DView);
     RenderInfoBar(DView->RenderRP, 255);
	FrameEvent();
	SwitchView(DView);

 if(Mouse)
  if(WaitMouse())
	 return IAL_LMB;
  else return IAL_OK;
 else
	return IAL_OK;
}

//--------------------------------------------------------------------
LONG SKUL_Sequence(UBYTE *Obj,ANIM_COMMAND *AnimLista,UBYTE *Back,UWORD *Env,UBYTE *Shine)
{
SCENE *Scene;

	if((Scene = EM_RelocScene(Obj)) == NULL) return 1L;

     EM_Back=Back;
/*
Object: CONE.9 (0) - zeby
Object: AXIS (1) - glowa
Object: Circle_4-6 (2) - kolce
*/

		SetObjectFlags(&Scene->Objects[0],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE | OF_ENVIRONMENT,
									 FF_TEXTURE | FF_ENVIRONMENT |(1L<<16));
		SetObjectFlags(&Scene->Objects[1],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE | OF_ENVIRONMENT | OF_NOBACKFACE,
									 FF_TEXTURE | FF_ENVIRONMENT);
		SetObjectFlags(&Scene->Objects[2],
									 OF_NEWPOS | OF_DISPLAY | OF_TEXTURE | OF_ENVIRONMENT,
									 FF_TEXTURE | OF_ENVIRONMENT |(1L<<16));

	EnvMapPtr = &Env[256*128];
	ShineLUTPtr = Shine;

	TM_DoAnim(DView, Scene, AnimLista, SKUL_RenderFrame);

	EM_FreeScene(Scene);

	return SEQ_OK;
}

LONG SKUL_RenderFrame(DVIEW *DView, SCENE *Scene)
{
FACE *tmpFace;
LONG VisibleFacesNumber;
LONG i;
LONG TM;

	TM_TransformScene(Scene);
	VisibleFacesNumber = TM_CreateDepthBuffer(Scene, Scene->DeptBuffor);
	TM_SortDepthBuffer(Scene->DeptBuffor, VisibleFacesNumber);

  ClearBack(DView->Chunky,EM_Back);

	for(i=0; i<VisibleFacesNumber; i++)
	{
		tmpFace = Scene->DeptBuffor[i];
          TM = (tmpFace->Flags & 0x00ff0000) >> 16;
          TxtMapPtr = EnvMaps[TM];

		RenderFace(tmpFace);
	}

	SafeRender(DView);
	DView->C2P(DView);
  RenderInfoBar(DView->RenderRP, 255);
	FrameEvent();
	SwitchView(DView);
	return IAL_OK;
}

VOID SetObjectFlags(OBJECT *Object,ULONG OFlags, ULONG FFlags)
{
  LONG i;

	Object->Flags |= OFlags;

	for(i=0;i<Object->FNumber;i++)
		Object->Faces[i].Flags = FFlags;
}
