/* LICENSE:
  =========================================================================
    CMPack'04 Source Code Release for OPEN-R SDK 1.1.5-r2 for ERS7
    Copyright (C) 2004 Multirobot Lab [Project Head: Manuela Veloso]
    School of Computer Science, Carnegie Mellon University
    All rights reserved.
  ========================================================================= */

#ifndef __LEARN_H__
#define __LEARN_H__

#include <stdio.h>
#include <string.h>

#include "agent/Vision/colors.h"

typedef unsigned char uchar;
typedef unsigned long ulong;

#define LEVELS 256
#define COLORS 16

struct example{
  uchar label;
  uchar y,u,v;
  example *next;

  uchar val(int i)
    {return(((uchar*)&this->y)[i]);}
};

struct color_info{
  char *name;
  rgb rcolor;
  double weight,confidence;
#ifdef USE_AMBIGUOUS
  double confidenceHigh;
#endif
};

class WeightProp {
private:
  double *wprop;

  int mapSize;
  int numColors;
  int numProps;

  int calcIdx(int map_idx, int color_idx, int prop_id) {
    return (map_idx * numColors + color_idx) * numProps + prop_id;
  }

public:
  WeightProp() {
    wprop=NULL;
  }

  void init(int map_size, int num_colors, int num_props) {
    mapSize   = map_size;
    numColors = num_colors;
    numProps  = num_props;
    wprop = new double[mapSize*numColors*numProps];
    memset(wprop,0,sizeof(double)*mapSize*numColors*numProps);
  }
  void release() {
    delete[] wprop;
    wprop=NULL;
  }

  double &idxProp(int map_idx, int color_idx, int prop_id) {
    return wprop[calcIdx(map_idx,color_idx,prop_id)];
  }
};

class thresh{
public:
  double *wmap; // weight map
  WeightProp wprop; // weight properties map
  ulong *count; // color example count

  example **ltable;
  int size;
  int size_y,size_u,size_v;
  int div_y,div_u,div_v;

  int loc(int y,int u,int v) {
    return(((y/div_y)*size_u + u/div_u)*size_v + v/div_v);
  }

  int box_loc(int y_box, int u_box, int v_box) {
    return ((y_box*size_u + u_box)*size_v + v_box);
  }

public:
  uchar *tmap;

  thresh() {ltable=NULL; tmap=NULL; count=NULL;}
  ~thresh() {clear();}

  bool init(int sy,int su,int sv);
  void clear();

  void addList(example *e);
  uchar classify(int y,int u,int v)
    {return(tmap[loc(y,u,v)]);}

  double calcWeightTwoSide(double gamma, int mind, int maxd);
  double calcWeightOneHere(uchar ymin, uchar umin, uchar vmin, example *ex, WeightProp &wprop, int map_idx, int color_idx);
  double calcWeightOneYP  (uchar ymin, uchar umin, uchar vmin, example *ex, double *prop);
  double calcWeightOneYM  (uchar ymin, uchar umin, uchar vmin, example *ex, double *prop);
  void calcWeightPropHere();
  void addWeightPropYP();
  void addWeightPropYM();
  void sweepWeightMapVP();
  void sweepWeightMapVM();
  // propagate weight to u +(plus) square
  void sweepWeightMapUP();
  // propagate weight to u -(minus) square
  void sweepWeightMapUM();
  void copyWeightProp();
  void fillInWeightMap(color_info *colors, int num);
  void learnMap(color_info *colors,int num);
};

#endif
// __LEARN_H__
