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

#include "picture.h"
#include "decode.h"

#define TRUE  1
#define FALSE 0

main(int argc, char *argv[])
{
  vga_modeinfo    *vgamode;
  int             i,data,video,bank,f,c;
  int             i256 = 0, i32k = 0, i16m = 0, this;
  int             gray = 0, delay = -1, endless = 0, first = 1;
  unsigned int    pixel;
  struct PICTURE  picture;
  FILE            *fp;
  unsigned char   *mem;

  /* arguments ok ? */
  if (argc < 2) {
    printf("this program displays PhotoCD-images using svgalib\n");
    printf("usage:    pcdview [ -e -g -d time ] filename ...\n");
    printf("options:  -e       endless loop\n");
    printf("          -g       display grayscaled images\n");
    printf("          -d time  instead of waiting for a keypress\n");
    printf("                   before displaying next picture, sleep\n");
    printf("                   >time< secounds\n");
    return(0); }

  /* getopt */
  for (;;) {
    c = getopt(argc, argv, "d:eg");
    if (c == -1)
      break;
    switch (c) {
    case 'e':
      endless = TRUE;
      break;
    case 'd':
      delay = atoi(optarg);
      break;
    case 'g':
      gray = TRUE;
      break;
    case ':':
    case '?':
      exit(0);
    }
  }

  /* initialisation - we are looking for a 800x600x256 or 800x600x32k-mode
   * (or 16M colors, but this doen'nt work) */
  vga_init();
  for (this = 0, i = 1;; i++) {
    vgamode = vga_getmodeinfo(i);
    if (vgamode == NULL) break;
    if ((vga_hasmode(i)) && 
	(vgamode->width==800) && 
	(vgamode->height==600) &&
	((vgamode->colors==256) || (vgamode->colors==32768) || vgamode->colors==(1 << 24))) {
      if (vgamode->colors == 256)       i256 = i;
      if (vgamode->colors == 32768)     i32k = i;
      if (vgamode->colors == (1 << 24)) i16m = i;
    }
  }
  if (i256) this = i256;
  if (i32k) this = i32k;
  /* True color is'nt supported yet
  if (i16m) this = i16m;
  */
  if (gray && i256) this = i256;
  if (this == 0) {
    printf("sorry, no 800x600 grapics mode with 256 or 32k colors found.");
    return(0);
  }
  vgamode = vga_getmodeinfo(this);
  printf("\nuse mode %i: %ix%ix%i\n",
	 this,vgamode->width,vgamode->height,vgamode->colors);

  /* OK, mode found. switch on */
  vga_setmode(this);
  mem = vga_getgraphmem();
  
  /* get memory */
  picture.x = 768;
  picture.y = 512;
  picture.data = malloc(3*768*512);
  if (picture.data == NULL) {
    printf("out of memory\n");
    return(0); }

  for (f = 1; f < argc || endless; f++) {
    /* read picture */
    if (endless && (f == argc))
      f = 1;
    if (argv[f][0] == '-')
      continue;
    fp = fopen(argv[f],"r");
    if (fp == NULL) {
      /* ignore */
      continue; }
    fseek(fp, 196608, SEEK_SET);

    switch (vgamode->colors) {
    case 256:
      decode_gray(fp,&picture);
      break;
    case 32768:
      decode_32k(fp,&picture);
      break;
    case (1 << 24):
      decode(fp,&picture);
      break;
    }

    fclose(fp);

    if (!first) {
      if (-1 == delay)
	getchar();
      else
	sleep(delay);
    } else
      first = 0;
    
    /* OK, now display image */
    vga_setpage(0);
    switch (vgamode->colors) {
    case 256:
      for (i = 0; i < 256; i++) {
	vga_setpalette(i,i>>2,i>>2,i>>2); }
      for (data = 0, video = 0, bank = 0; data < 768*512; data +=768, video += 800) {
	if (video+768 >= 65536) {
	  /* zeile mit bank grenze */
	  memcpy(&mem[video],&picture.data[data],65536-video);
	  vga_setpage(++bank);
	  memcpy(mem,&picture.data[data+(65536-video)],768-(65536-video));
	  video -= 65536;
	} else {
	  memcpy(&mem[video],&picture.data[data],768);
	}
      }
      break;
    case 32768:
      for (data = 0, video = 0, bank = 0; data < 2*768*512; data+=2*768, video += 2*800) {
	if (video+2*768 >= 65536) {
	  /* zeile mit bank-grenze */
	  memcpy(&mem[video],&picture.data[data],65536-video);
	  vga_setpage(++bank);
	  memcpy(mem,&picture.data[data+(65536-video)],2*768-(65536-video));
	  video -= 65536;
	} else {
	  memcpy(&mem[video],&picture.data[data],2*768);
	}
      }
      break;
    case (1 << 24):
      /* may be, someone add's trucolor here ???  I will not do this because can't test this */
      break;
    default:
      /* oops */
      printf("internal error\n");
      vga_setmode(TEXT);
      exit(1);
    }
  }

  if (-1 == delay) {
    getchar();
  } else {
    sleep(delay);
  }
  
  vga_setmode(TEXT);
  
  return(0);
}






