/********************************************************************
 FILENAME: VIEW_IO.CPP
 AUTHOR  : JAKE HILL
 DATE    : 12/1/94

 Copyright (c) 1994 by Jake Hill:
 If you use any part of this code in your own project, please credit
 me in your documentation and source code.  Thanks.
********************************************************************/

#include "VIEW.HPP"
#include "TRIG.HPP"

#include <io.h>
#include <dos.h>                // int86
#include <fcntl.h>
#include <conio.h>              // kbhit, getch
#include <stdio.h>              // printf
#include <string.h>
#include <process.h>            // exit

// Some more yucky global variables.
short NumThings;
short NumSegs;
short NumSides;
short NumLines;
short NumNodes;
short NumSectors;
short NumSSectors;
short NumVertexes;
short BlockmapSize;

// Sets the graphics mode.
void setmode(unsigned short n)
{
   union REGS inregs, outregs;

   inregs.x.ax = n;
   int86(0x10, &inregs, &outregs);
};

// This function opens the wadfile, determines if it is a PWAD
// or an IWAD, then reads in the resources for THINGS, LINES, SIDES,
// VERTEXES, SEGS, SSECTORS, NODES, and SECTORS.
void View::OpenWad(char *WadName, long Level)
{
   int handle;
   short EntriesRead = 0;
   unsigned long EntryOffset = 0;

   WAD_Header HEADER;
   Directory_Entry DIRECTORY;

   handle = open( WadName ,O_BINARY|O_RDONLY);
   if (handle == (-1))
   {
      printf("ERROR:Could not open file %s.\n",WadName);
      exit(-1);
   }

   read(handle, &HEADER, sizeof(WAD_Header));

   if ( strnicmp(HEADER.signature, "IWAD", 4) == 0 )
   {
      printf("Reading IWAD file.\n");
// We need to skip past the PLAYPAL, and DEMO stuff if in an IWAD.
      HEADER.foffset += 6L * sizeof(Directory_Entry);
   }
   else if ( strnicmp(HEADER.signature, "PWAD", 4) == 0 )
   {
      printf("Reading PWAD file.\n");
   }
   else
   {
      printf("This is not a valid WAD file!\n");
      exit(-1);
   }

   printf("This file contains %d directory entries.\n\n", HEADER.num_entries);
   EntryOffset += HEADER.foffset + (Level*11L*sizeof(Directory_Entry));

   while ( EntriesRead < 11 )
   {
      lseek(handle, EntryOffset, SEEK_SET);
      read(handle, &DIRECTORY, sizeof(Directory_Entry));

      if ( strnicmp( DIRECTORY.name, "THINGS", 6 ) == 0 )
         LoadThings( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "LINEDEFS", 8 ) == 0 )
         LoadLines( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "SIDEDEFS", 8 ) == 0 )
         LoadSides( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "VERTEXES", 8 ) == 0 )
         LoadVertexes( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "SEGS", 4 ) == 0 )
         LoadSegs( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "SSECTORS", 8 ) == 0 )
         LoadSSectors( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "NODES", 5 ) == 0 )
         LoadNodes( &DIRECTORY, handle );
      else if ( strnicmp( DIRECTORY.name, "SECTORS", 7 ) == 0 )
         LoadSectors( &DIRECTORY, handle );
      else
         printf("Skipping %8s.\n",DIRECTORY.name);

      EntriesRead++;
      EntryOffset += sizeof( Directory_Entry );
   }
   printf("Allocated memory for arrays...\n");

   close(handle);
   InitTrig();

   printf("Press Any key to continue...\n");
   while ( !kbhit() );
   getch();

   setmode(19);
};

// All of the following procedures read in the indicated
// resource from a WAD file pointed to by handle.

void View::LoadThings( Directory_Entry *Dir, int handle )
{
   float angle;
   NumThings = (short) (Dir->size / sizeof(thing));
   thing *Thing_Array = new thing [ NumThings ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Thing_Array, (unsigned int) Dir->size);

   for (short i=0; i<NumThings; i++)
      if ( Thing_Array[i].thing_type == 1 )
      {
         angle = (float) (182.0444444444444 * (float) Thing_Array[i].angle);
         SetView( Thing_Array[i].x, Thing_Array[i].y, 40, (unsigned short) angle);
         break;
      }

   printf("THINGS   : %d\n", NumThings);
   delete [] Thing_Array;
}

void View::LoadSegs( Directory_Entry *Dir, int handle )
{
   NumSegs = (short) (Dir->size / sizeof(seg));
   Seg_Array = new seg [ NumSegs ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Seg_Array, (unsigned int) Dir->size);

   printf("SEGS     : %d\n", NumSegs);
}

void View::LoadSides( Directory_Entry *Dir, int handle )
{
   NumSides = (short) Dir->size/sizeof(side);
   Side_Array = new side [ NumSides ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Side_Array, (unsigned int) Dir->size);

   printf("SIDEDEFS : %d\n", NumSides);
}

void View::LoadLines( Directory_Entry *Dir, int handle )
{
   NumLines   = (short) (Dir->size / sizeof(line));
   Line_Array = new line [ NumLines ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Line_Array, (unsigned int)Dir->size);

   printf("LINEDEFS : %d\n", NumLines);
}

void View::LoadNodes( Directory_Entry *Dir, int handle )
{
   NumNodes = (short) Dir->size/sizeof(node);
   Node_Array = new node [ NumNodes ];
   PNode_Array = new node * [ NumNodes ];

   MaxNode  = NumNodes - 1;

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Node_Array, (unsigned int) Dir->size);

   for (int i=0; i<NumNodes; i++)
      PNode_Array[i] = &Node_Array[i];

   printf("NODES    : %d\n", NumNodes);
}

void View::LoadSectors( Directory_Entry *Dir, int handle )
{
   NumSectors = (short) Dir->size/sizeof(sector);
   Sector_Array = new sector [ NumSectors ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Sector_Array, (unsigned int) Dir->size);

   printf("SECTORS  : %d\n", NumSectors);
}

void View::LoadVertexes( Directory_Entry *Dir, int handle )
{
   NumVertexes = (short) Dir->size/sizeof(vertex);
   Vertex_Array = new vertex [ NumVertexes ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  Vertex_Array, (unsigned int) Dir->size);

   printf("VERTEXES : %d\n", NumVertexes);
}

void View::LoadSSectors( Directory_Entry *Dir, int handle )
{
   NumSSectors = (short) Dir->size/sizeof(ssector);
   SSector_Array = new ssector [ NumSSectors ];

   lseek(handle, Dir->foffset, SEEK_SET);
   read(handle,  SSector_Array, (unsigned int) Dir->size);

   printf("SSECTORS : %d\n", NumSSectors);
}

// Returns the screen mode to normal text.
void View::Close(void)
{
   setmode(3);
};
