/*
 * Copyright (c) 1992 The Regents of the University of California.
 * All rights reserved.
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement is
 * hereby granted, provided that the above copyright notice and the following
 * two paragraphs appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * This file has been changed by Niklas Rjemo 1993.
 * 
 */
#include <math.h>
#include "video.h"
#include "dither.h"


#include "wimp.h"        /*  access to WIMP SWIs                      */
#include "win.h"         /*  registering window handlers              */
#include "wimpt.h"
#include "baricon.h"
#include "res.h"         /*  access to resources                      */
#include "resspr.h"      /*  sprite resources                         */
#include "menu.h"
#include "flex.h"        /*  dynamic mem alloc from WIMP              */
#include "template.h"    /*  reading in template file                 */
#include "dbox.h"
#include "werr.h"
#include "colourtran.h"
#include "sprite.h"
#include "mpegplay.h"

extern sprite_pixtrans mpeg_trans[256];     /* colour translation table     */

/* Array that remaps color numbers to actual pixel values used by X server. */

unsigned char pixel[256];

/* Arrays holding quantized value ranged for lum, cr, and cb. */

int lum_values[LUM_RANGE];
int cr_values[CR_RANGE];
int cb_values[CB_RANGE];

/* Declaration of global variable containing dither type. */

extern int ditherType;


/*
 *--------------------------------------------------------------
 *
 * InitColor --
 *
 *      Initialized lum, cr, and cb quantized range value arrays.
 *
 * Results: 
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void
InitColor()
{
  int i;

  for (i=0; i<LUM_RANGE; i++) {
    lum_values[i] = ((i * 256) / (LUM_RANGE)) + (256/(LUM_RANGE*2));
  }

  for (i=0; i<CR_RANGE; i++) {
    cr_values[i] = ((i * 256) / (CR_RANGE)) + (256/(CR_RANGE*2));
  }

  for (i=0; i<CB_RANGE; i++) {
    cb_values[i] = ((i * 256) / (CB_RANGE)) + (256/(CB_RANGE*2));
  }

}


/*
 *--------------------------------------------------------------
 *
 * ConvertColor --
 *
 *      Given a l, cr, cb tuple, converts it to r,g,b.
 *
 * Results:
 *      r,g,b values returned in pointers passed as parameters.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

static void
ConvertColor(l, cr, cb, r, g, b)
     unsigned char l, cr, cb;
     unsigned char *r, *g, *b;
{
  double fl, fcr, fcb, fr, fg, fb;

  fl = (double) l;
  fcr =  ((double) cr) - 128.0;
  fcb =  ((double) cb) - 128.0;


  fr = fl + (1.40200 * fcb);
  fg = fl - (0.71414 * fcb) - (0.34414 * fcr);
  fb = fl + (1.77200 * fcr);

  if (fr < 0.0) fr = 0.0;
  else if (fr > 255.0) fr = 255.0;

  if (fg < 0.0) fg = 0.0;
  else if (fg > 255.0) fg = 255.0;

  if (fb < 0.0) fb = 0.0;
  else if (fb > 255.0) fb = 255.0;

  *r = (unsigned char) fr;
  *g = (unsigned char) fg;
  *b = (unsigned char) fb;

}

/* Array back mapping pixel value to color number. Used for debugging and dumping
   purposes. 
*/

static char backpixel[256];


/*
 *--------------------------------------------------------------
 *
 * ResizeDisplay --
 *
 *      Resizes display window.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void ResizeDisplay(int w, int h)
{
  if (ditherType == NO_DITHER) return;

  mpeg_resize(FALSE,w,h);
}

#if 0

/*
 *--------------------------------------------------------------
 *
 * MakeWindow --
 *
 *      Create X Window
 *
 * Results:
 *      Read the code.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */
static void iconclick(wimp_i icon)
{
  icon = icon; /* We don't need the handle: this stops compiler warning */

#if 0
  /* Open the window - only one allowed */
  if (window_open)
    werr(FALSE, "Only one window may be opened");
  else
#endif
  {
    wimp_wstate  state;

    /* Get the state of the window */
    if (wimpt_complain(wimp_get_wind_state(handle, &state)) == 0)
    {
      state.o.behind = -1;          /* Make sure window is opened in front */
      wimpt_noerr(wimp_open_wind(&state.o));
    }
  }
}

int riscosMenu(void);

int initWimp(void)
{
  wimp_wind *window;

  wimpt_init("MPEG Play");
  res_init("MPEGPlay");          /* Resources */
  resspr_init();                   /* Application sprites */
  template_init();                 /* Templates */
#if 0
  dbox_init();
#endif

  flex_init();
  heap_init(FALSE);

  window = template_syshandle("Pic");
  if (window == 0) {
    fprintf (stderr, "Couldn't find template 'Pic'.\n");
    exit (-1);
  }

  wimpt_noerr(wimp_create_wind(window, &handle));
  /* Create the menu tree */
  if(!riscosMenu())
    return FALSE;

  baricon("!mpegplay", (int)resspr_area(), iconclick);
#if 0
  if (!event_attachmenu(win_ICONBAR, iconMenu, iconMenuProc, 0))
    return FALSE; /* Unable to attach menu */
#endif
  return TRUE;
}

#endif

static void 
MakeWindow() 
{

  if (ditherType == NO_DITHER) return;
  if (ditherType == FULL_COLOR_DITHER) {
    fprintf (stderr, "-color option only valid on full color display.\n");
    exit (-1);
  }

}
  

/*
 *--------------------------------------------------------------
 *
 * InitDisplay --
 *
 *      Initialized display, sets up colormap, etc.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void InitDisplay()
{
  wimp_paletteword value;
  int gcol;
  int ncolors = LUM_RANGE*CB_RANGE*CR_RANGE;
  int i, lum_num, cr_num, cb_num;
  unsigned char r, g, b;

  if (ditherType == NO_DITHER) return;

  MakeWindow();
  wimpt_checkmode();

  for (i=0; i<ncolors; i++) {

    lum_num = (i / (CR_RANGE*CB_RANGE))%LUM_RANGE;
    cr_num = (i / CB_RANGE)%CR_RANGE;
    cb_num = i % CB_RANGE;

    ConvertColor(lum_values[lum_num], cr_values[cr_num], cb_values[cb_num], &r, &g, &b);

    value.bytes.red = r;
    value.bytes.green = g;
    value.bytes.blue = b;
    wimpt_noerr(colourtran_return_GCOLformode(value,21,0,&gcol));
    wimpt_noerr(colourtran_GCOL_tocolournumber(gcol,&gcol));
    pixel[i] = gcol;
    backpixel[gcol] = i;
  }
}


/*
 *--------------------------------------------------------------
 *
 * InitGrayDisplay --
 *
 *      Initialized display for gray scale dither.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

#define NUM_COLORS 128

void InitGrayDisplay()
{
  wimp_paletteword value;
  int gcol;
  int ncolors = NUM_COLORS;
  int i;

  MakeWindow();

  for (i=0; i<ncolors; i++) {

    value.bytes.red = i*2;
    value.bytes.green = i*2;
    value.bytes.blue = i*2;
    wimpt_noerr(colourtran_return_GCOLformode(value,21,0,&gcol));
    wimpt_noerr(colourtran_GCOL_tocolournumber(gcol,&gcol));
    pixel[(i*2)] = gcol;
    pixel[(i*2)+1] = gcol;
    backpixel[gcol] = i;
  }

}


/*
 *--------------------------------------------------------------
 *
 * InitMonoDisplay --
 *
 *      Initialized display for monochrome dither.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void InitMonoDisplay()
{
  MakeWindow();
#if 0
  black = 1;
  white = 0;
#endif
}

#if 0
/*
 *--------------------------------------------------------------
 *
 * InitColorDisplay --
 *
 *      Initialized display for full color output.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void InitColorDisplay()
{
  fprintf(stderr,"InitColorDisplay\n");
  exit(-1);
}
#endif


/*
 *--------------------------------------------------------------
 *
 * ExecuteDisplay --
 *
 *      Actually displays display plane in previously created window.
 *
 * Results:
 *      None.
 *
 * Side effects:
 *      None.
 *
 *--------------------------------------------------------------
 */

void
ExecuteDisplay(VidStream *vid_stream)
{
  totNumFrames++;
  fprintf (stderr, "%d ", totNumFrames);

  if (ditherType == NO_DITHER) return;

  showBits((char *) vid_stream->current->display);
}
