/*
        FYEO : Process
        Frank Lyonnet 1992
*/

#include <stdio.h>
#include <time.h>
#include "C:kernel.h"
#include "jinclude.h"
#include "RISC_OSLib:menu.h"
#include "RISC_OSLib:wimp.h"
#include "RISC_OSLib:template.h"
#include "RISC_OSLib:sprite.h"
#include "MyThread.h"
#include "Filetypes.h"
#include "Erreur.h"
#include "Display.h"
#include "Process.h"
#include "Time.h"
#include "FYEOMem.h"
#include "Bool.h"
#include "Modes.h"


// Rick 2004/01/29: This is used in "JRDJFIF" to jpegtran the
// file if it is a progressive JPEG (or, if we suspect it is...)
char JPEGFileName[256] = "";

/* Wanted colorspace*/
static int OutColorspace;

/* The thread*/
static my_thread Thread;

/* The input file , to be closed on abort */
static FILE *Input;

/* Def in other pipe manager*/
extern void other_decompress(compress_info_ptr cinfo);

/* Compress progress monitor , not used , must be defined */
METHODDEF void
    c_progress_monitor(compress_info_ptr cinfo, long loopcounter, long looplimit) {
   /* do nothing */
}

/* Decompress progress monitor , not used , must be defined */
METHODDEF void
    d_progress_monitor(decompress_info_ptr cinfo, long loopcounter, long looplimit) {
   /* do nothing */
}

/* Call back to ui after image init */
METHODDEF void c_ui_method_selection(compress_info_ptr cinfo) {
   if (cinfo->in_color_space == CS_GRAYSCALE)
      cinfo->jpeg_color_space = CS_GRAYSCALE;
   else
      cinfo->jpeg_color_space = CS_RGB;

   if (OutColorspace==FYEO_GRAY)
      cinfo->jpeg_color_space = CS_GRAYSCALE;

   jselwmacorn_comp(cinfo);
}

/* Gif to sprite thread */
static void FYEO_gif_to_sprite(char *InputFilename, FYEO_display * Display) {
 struct Compress_info_struct cinfo;
 struct Compress_methods_struct c_methods;
 struct External_methods_struct e_methods;

   cinfo.methods = &c_methods;
   cinfo.emethods = &e_methods;
   jselerror(&e_methods);
   jselmemmgr(&e_methods);
   c_methods.c_ui_method_selection = c_ui_method_selection;

   cinfo.methods->progress_monitor = c_progress_monitor;

   cinfo.output_sprite = Display -> Sprite;

   cinfo.special_speed = FALSE;

   cinfo.output_area_width = Display -> PixWidth;
   cinfo.output_area_height = Display -> PixHeight;

   cinfo.x_scale_mul = Display -> XMul;
   cinfo.x_scale_div = Display -> XDiv;
   cinfo.y_scale_mul = Display -> YMul;
   cinfo.y_scale_div = Display -> YDiv;

   #ifdef DEBUG
      e_methods.trace_level++;
   #endif

   OutColorspace = Display -> Colorspace;

   cinfo.input_file = fopen(InputFilename, "r");

   /* Save FILE * for abort */
   Input = cinfo.input_file;
   jselrgif(&cinfo);

   other_decompress((void *) &cinfo);

   fclose(cinfo.input_file);

   /* Thread terminate */
   my_thread_leave(END);
}


/* BMP to sprite thread [RICK 2004/02/25] */
static void FYEO_bmp_to_sprite(char *InputFilename, FYEO_display * Display)
{
   struct Compress_info_struct cinfo;
   struct Compress_methods_struct c_methods;
   struct External_methods_struct e_methods;

   cinfo.methods = &c_methods;
   cinfo.emethods = &e_methods;
   jselerror(&e_methods);
   jselmemmgr(&e_methods);
   c_methods.c_ui_method_selection = c_ui_method_selection;

   cinfo.methods->progress_monitor = c_progress_monitor;

   cinfo.output_sprite = Display -> Sprite;

   cinfo.special_speed = FALSE;

   cinfo.output_area_width = Display -> PixWidth;
   cinfo.output_area_height = Display -> PixHeight;

   cinfo.x_scale_mul = Display -> XMul;
   cinfo.x_scale_div = Display -> XDiv;
   cinfo.y_scale_mul = Display -> YMul;
   cinfo.y_scale_div = Display -> YDiv;

   #ifdef DEBUG
      e_methods.trace_level++;
   #endif

   OutColorspace = Display -> Colorspace;

   cinfo.input_file = fopen(InputFilename, "r");

   /* Save FILE * for abort */
   Input = cinfo.input_file;

   jselrbmp(&cinfo);
   other_decompress((void *) &cinfo);

   fclose(cinfo.input_file);

   /* Thread terminate */
   my_thread_leave(END);

   return;
}


/** Targa to sprite thread */
static void FYEO_targa_to_sprite(char *InputFilename, FYEO_display * Display) {
 struct Compress_info_struct cinfo;
 struct Compress_methods_struct c_methods;
 struct External_methods_struct e_methods;

   cinfo.methods = &c_methods;
   cinfo.emethods = &e_methods;
   jselerror(&e_methods);
   jselmemmgr(&e_methods);
   c_methods.c_ui_method_selection = c_ui_method_selection;

   cinfo.methods->progress_monitor = c_progress_monitor;

   cinfo.output_sprite = Display -> Sprite;

   cinfo.special_speed = FALSE;

   cinfo.output_area_width = Display -> PixWidth;
   cinfo.output_area_height = Display -> PixHeight;

   cinfo.x_scale_mul = Display -> XMul;
   cinfo.x_scale_div = Display -> XDiv;
   cinfo.y_scale_mul = Display -> YMul;
   cinfo.y_scale_div = Display -> YDiv;

   #ifdef DEBUG
      e_methods.trace_level++;
   #endif

   OutColorspace = Display -> Colorspace;

   cinfo.input_file = fopen(InputFilename, "r");

   /* Save FILE * for abort */
   Input = cinfo.input_file;
   jselrtarga(&cinfo);

   other_decompress((void *) &cinfo);

   fclose(cinfo.input_file);

   /* Thread terminate */
   my_thread_leave(END);
}

/** PPM to sprite thread */
static void FYEO_ppm_to_sprite(char *InputFilename, FYEO_display * Display) {
struct Compress_info_struct cinfo;
struct Compress_methods_struct c_methods;
struct External_methods_struct e_methods;

   cinfo.methods = &c_methods;
   cinfo.emethods = &e_methods;
   jselerror(&e_methods);
   jselmemmgr(&e_methods);
   c_methods.c_ui_method_selection = c_ui_method_selection;

   cinfo.methods->progress_monitor = c_progress_monitor;

   cinfo.output_sprite = Display -> Sprite;

   cinfo.special_speed = FALSE;

   cinfo.output_area_width = Display -> PixWidth;
   cinfo.output_area_height = Display -> PixHeight;

   cinfo.x_scale_mul = Display -> XMul;
   cinfo.x_scale_div = Display -> XDiv;
   cinfo.y_scale_mul = Display -> YMul;
   cinfo.y_scale_div = Display -> YDiv;

   #ifdef DEBUG
      e_methods.trace_level++;
   #endif

   OutColorspace = Display -> Colorspace;

   cinfo.input_file = fopen(InputFilename, "r");

   /* Save FILE * for abort */
   Input = cinfo.input_file;
   jselrppm(&cinfo);

   other_decompress((void *) &cinfo);

   fclose(cinfo.input_file);

   /* Thread terminate */
   my_thread_leave(END);
}

/** Back to ui after image init */
static void d_ui_method_selection(decompress_info_ptr cinfo) {
   if (cinfo->jpeg_color_space == CS_GRAYSCALE)
      cinfo->out_color_space = CS_GRAYSCALE;
   else
      cinfo->out_color_space = CS_YCbCr;

   if (OutColorspace==FYEO_GRAY)
      cinfo->out_color_space = CS_GRAYSCALE;

   jselwmacorn_decomp(cinfo);
}

/** JPEG to sprite thread */
static void FYEO_jpeg_to_sprite(char *InputFilename, FYEO_display * Display) {
struct Decompress_info_struct cinfo;
struct Decompress_methods_struct dc_methods;
struct External_methods_struct e_methods;

   cinfo.methods = &dc_methods;
   cinfo.emethods = &e_methods;
   jselerror(&e_methods);
   jselmemmgr(&e_methods);
   dc_methods.d_ui_method_selection = d_ui_method_selection;

   cinfo.methods->progress_monitor = d_progress_monitor;

   j_d_defaults(&cinfo, TRUE);

   cinfo.output_sprite = Display -> Sprite;

   cinfo.output_area_width = Display -> PixWidth;
   cinfo.output_area_height = Display -> PixHeight;

   cinfo.x_scale_mul = Display -> XMul;
   cinfo.x_scale_div = Display -> XDiv;
   cinfo.y_scale_mul = Display -> YMul;
   cinfo.y_scale_div = Display -> YDiv;

   /* Can have special speed */
   cinfo.special_speed = TRUE;

   #ifdef DEBUG
      e_methods.trace_level++;
   #endif

   OutColorspace = Display -> Colorspace;

   strncpy(JPEGFileName, InputFilename, 256); // RICK 2004/01/29
   cinfo.input_file = fopen(InputFilename, "r");

   /* Save FILE * for abort */
   Input = cinfo.input_file;

   jselrjfif(&cinfo);

   jpeg_decompress((void *) &cinfo);

   fclose(cinfo.input_file);
   my_thread_leave(END);
}

/* Process init */
BOOL FYEO_init_process(FYEO_process * Process) {
   Process->CBefore = clock();
   Process->Display->ProcessTime = 0;

   TIME_INIT

   Thread = NULL;

   switch (Process->Filetype) {
   case FILE_JPEG:
      if ((Thread = my_thread_init((void *) FYEO_jpeg_to_sprite,
            (void *) Process->FileName, (void *) Process->Display)) == NULL)
      {
         erreur("Unable to create process.");
         return (FALSE);
      }
      break;
   case FILE_GIF:
      if ((Thread = my_thread_init((void *) FYEO_gif_to_sprite,
            (void *) Process->FileName, (void *) Process->Display)) == NULL)
      {
         erreur("Unable to create process .");
         return (FALSE);
      };
      break;

      // Rick 2004/02/25
  case FILE_BMP:
      if ((Thread = my_thread_init((void *) FYEO_bmp_to_sprite,
            (void *) Process->FileName, (void *) Process->Display)) == NULL)
      {
         erreur("Unable to create process .");
         return (FALSE);
      };
      break;

  case FILE_PPM:
      if ((Thread = my_thread_init((void *) FYEO_ppm_to_sprite,
            (void *) Process->FileName, (void *) Process->Display)) == NULL)
      {
         erreur("Unable to create process .");
         return (FALSE);
      }
      break;
   case FILE_TARGA:
      if ((Thread = my_thread_init((void *) FYEO_targa_to_sprite,
            (void *) Process->FileName, (void *) Process->Display)) == NULL)
      {
         erreur("Unable to create process .");
         return (FALSE);
      }
      break;
   default:
      erreur_interne("Bad filetype when initiating process");
      break;
   };

   /* A first call to check if it's worth displaying the window */
   switch (my_thread_enter(Thread)) {
   case OK:
      return (TRUE);
      break;
   case ERREUR:
      FYEO_abort_process(Process);
      return (FALSE);
      break;
   case END:
      return (FALSE);
      break;
   default:
      erreur_interne("Bad thread return code");
      return (FALSE);
      break;
   }
}

/* Do some process */
my_thread_return_code FYEO_do_process(FYEO_process * Process) {
   return (my_thread_enter(Thread));
}

/** Terminate process */
void FYEO_terminate_process(FYEO_process * Process) {
   Process->CAfter = clock();
   Process->Display->ProcessTime = ((float)Process->CAfter - (float)Process->CBefore) / (float)CLOCKS_PER_SEC;
   my_thread_destroy(Thread);
   TIME_TERM
}


void FYEO_abort_process(FYEO_process * Process) {
   /* Free ALL mem used by compress/decompress */
   FYEO_mem_term();

   /* Close file */
   fclose(Input);

   /* And destroy the thread */
   my_thread_destroy(Thread);
   TIME_TERM
}
