/* ---------------------------------------------------------------------
   (c) ED 2003
   Project      : PROJECT
   Function     : Histogram manager
   Module       : HIS
   File         : his.c
   Created      : 25-09-2003
   Modified     : 25-09-2003
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   Log

   0.0 25-09-2003 Created
   1.0 25-09-2003 Initial version

   --------------------------------------------------------------------- */
#ifdef __cplusplus
#error This is not C++. Please use a C compiler.
#endif

#include "ed/inc/his.h"
#include "ed/inc/sysalloc.h"
#include "ed/inc/sys.h"

#include <limits.h>

/* private macro definitions =========================================== */

#define ID "HIS"
#define VER "1.0"

/* private constants =================================================== */

#define COUNT_MAX 0xFFFFFFFFUL

enum
{
   WIDTH_MIN = 60
};

/* private types ======================================================= */

/* private structures ================================================== */

/* private functions =================================================== */

static void clr_usr (his_usr_s * a, size_t n)
{
   size_t i;

   for (i = 0; i < n; i++)
   {
      his_usr_s *p = a + i;

      p->full = 0;
      p->count = 0;
   }
}

/* public internal functions =========================================== */

/* entry points ======================================================== */

/* ---------------------------------------------------------------------
   his_sid ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
char const *his_sid (void)
{
   return ID;
}

/* ---------------------------------------------------------------------
   his_sver ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
char const *his_sver (void)
{
   return VER;
}

/* ---------------------------------------------------------------------
   his_create ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_s *his_create (size_t n)
{
   his_s *this = NULL;

   if (n > 0)
   {
      this = malloc (sizeof *this);
      if (this != NULL)
      {
         CLR (this, his_s);

         this->a = malloc (n * sizeof *this->a);

         if (this->a != NULL)
         {
            this->n = n;
            clr_usr (this->a, this->n);
         }
      }
   }
   return this;
}

/* ---------------------------------------------------------------------
   his_delete ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
void his_delete (his_s * this)
{
   if (this != NULL)
   {
      FREE (this->a);
      free (this);
   }
}

/* ---------------------------------------------------------------------
   his_clr ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_clr (his_s * this)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      CLR (this, his_s);
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   his_init ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_init (his_s * this
                    ,his_usr_s * a
                    ,size_t n
                    ,char const *id
                    ,uint width
)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      if (width >= WIDTH_MIN)
      {
         if (a != NULL && n != 0)
         {
            /* Enregistrer les coordonnees du tableau utilisateur */

            this->a = a;
            this->n = n;
         }
         clr_usr (this->a, this->n);
         this->id = id;
         this->width = width;
      }
      else
      {
         this->width = WIDTH_MIN;
         err = HIS_ERR_WIDTH;
      }
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}

#if HIS_OUT
/* ---------------------------------------------------------------------
   his_install_out ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_install_out (his_s * this, his_out_f * pf, void *p_usr)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      this->pf = pf;
      this->p_usr = p_usr;
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}
#endif

#if HIS_OUT
/* ---------------------------------------------------------------------
   his_in ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_in (his_s * this, int data)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      if (this->pf != NULL)
      {
         int ret = (*this->pf) (this->p_usr, data);
         if (ret != 0)

         {
            err = HIS_ERR_CB_OUT;
         }
      }
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}
#endif

/* ---------------------------------------------------------------------
   his_probe ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_probe (his_s * this, size_t data)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      if (data < this->n)
      {
         his_usr_s *p = this->a + data;

         if (p->count < COUNT_MAX)
         {
            p->count++;
            p->full = p->count == COUNT_MAX;

            if (this->max < p->count)
            {
               this->max = p->count;
            }
         }
      }
      else
      {
         err = HIS_ERR_DATA;
      }
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   his_print_hor ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_print_hor (his_s * this)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      size_t i;

      for (i = 0; i < this->n; i++)
      {
         his_usr_s *p = this->a + i;

         printf ("%04lu|", (ulong) p->count);
      }
      printf ("max=%04lu\n", (ulong) this->max);

      printf ("\n");

      for (i = 0; i < this->max; i++)
      {
         size_t j;
         for (j = 0; j < this->n; j++)
         {
            his_usr_s *p = this->a + j;
            int c;

            if (p->count < this->max - i - 1)
            {
               c = ' ';
            }
            else
            {
               c = '*';
            }
            printf (" %2c", c);
         }
         printf ("\n");

      }

      for (i = 0; i < this->n; i++)
      {
         printf (" %2u", (uint) i);
      }
      printf ("\n");

      printf ("\n");
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   his_print_ver ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
his_err_e his_print_ver (his_s * this)
{
   his_err_e err = HIS_OK;

   if (this != NULL)
   {
      if (this->width >= WIDTH_MIN)
      {
         ulong const k = 1 + (this->max / this->width);
         ulong const j_max = this->max / k;
         size_t i;

         printf ("'%s' max=%lu ('*'=%lu) (width=%lu)\n"
                 ,this->id
                 ,(ulong) this->max
                 ,(ulong) k
                 ,(ulong) j_max
            );

         for (i = 0; i < this->n; i++)
         {
            his_usr_s *p = this->a + i;
            ulong const k_count = p->count / k;

            printf ("[%4lu] %8lu|"
                    ,(ulong) i
                    ,(ulong) p->count);

            {
               ulong j;

               for (j = 0; j < j_max; j++)
               {
                  int c;

                  if (j < k_count)
                  {
                     c = '*';
                  }
                  else
                  {
                     c = ' ';
                  }
                  printf ("%c", c);
               }
            }

            if (p->full)
            {
               printf ("F");
            }
            printf ("\n");
         }
         printf ("\n");

         printf ("\n");
      }
      else
      {
         err = HIS_ERR_WIDTH;
      }
   }
   else
   {
      err = HIS_ERR_CONTEXT;
   }
   return err;
}

/* ---------------------------------------------------------------------
   his_id ()
   ---------------------------------------------------------------------

   ---------------------------------------------------------------------
   I:
   O:
   --------------------------------------------------------------------- */
char const *his_id (his_s * this)
{
   char const *sid = NULL;

   if (this != NULL)
   {
      sid = this->id;
   }
   return sid;
}

/* public data ========================================================= */

/* ---------------------------------------------------------------------
   Generated by NEW (c) ED 2.3
   Powered by C-code generator (c) ED 2003 1.0
   --------------------------------------------------------------------- */
