#ifndef ProcImage_h
#define ProcImage_h

#include <FL/Fl.H>
#include <FL/Fl_Group.H>
#include <FL/Fl_Browser.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>

#include <stdio.h>
#include <string.h>

#include "ImprovWrapper.h"
#include "FW/labImage.h"


class ProcImage : public Fl_Group {
    Fl_Menu_Button *menu;              // the GUI components of this class
    Fl_Box *box;
    Fl_Button *button;
    Fl_Browser *browser;

    // input image
    Picture *p_input_img;
    // output image
    Picture *p_output_img;
    // camera image
    Picture *p_camera_img;
    
    // internal images
    Picture *p_img0;
    Picture *p_img1;

    // src and dest image 
    Picture *p_src;
    Picture *p_dst;

    IPLOP operations[MAX_IPL_OPS];     // list of ops for this image
    int num_ops;                       // number of operations on this image

    //double param[6];                   // parameters for operations
    double param[3];                   // parameters for operations

    bool is_colour;                    // true if image is colour
    bool *input_colour;                // true if input is colour
    bool *output_colour;               // true if output is colour
    bool *camera_colour;               // true if camera is colour
 
    bool enlarge;                    // true if enlarge enabled
    
    bool have_focus;                   // true if this object has focus

    Picture *p_image_buffer;             // image buffer for difference
    int buffer_flag;

    void (*param_cb)(double p[]);      // callback for parameters

    bool initialised;                  // flag for validation


public:
    ProcImage(int x, int y, int w, int h, const char *label=0);
        // Postcondition:
        //     Object is created in uninitialised state

    void initialize(Picture *p_in, Picture *p_out, Picture *p_cam, bool *in_colour,
                    bool *out_colour, bool *cam_colour);
        // Precondition:
        //     Pointers point to valid objects
        // Postcondition:
        //     Object can process images and display them

    void set_param_cb(void (*cb)(double p[]));
        // Precondition:
        //     cb points to a valid function
        // Postcondition:
        //     param_cb is now a pointer to the callback for when an
        //     operation is selected in the browser


    void add_op(IPLOP *op);
        // Precondition:
        //     op points to a filled IPLOP structure
        // Postcondition:
        //     op has been copied to the operations list
        //     num_ops' := num_ops + 1

    void remove_op(int n);
        // Precondition:
        //     The operations list contains at least n entries, n > 0
        // Postcondition:
        //     The nth entry has been removed from the operations list
        //     num_ops' := num_ops - 1

    void set_op(IPLOP *op, int n);
        // Precondition:
        //     op points to a filled IPLOP structure
        //     n >= 0
        // Postcondition:
        //     op has been copied to the nth position in the operations list

    void get_op(IPLOP *op, int n);
        // Precondition:
        //     op points to an IPLOP structure to be filled
        //     n >= 0
        // Postcondition:
        //     op is a copy of the nth operation in the operations list

    void save_ops(FILE *fp);
        // Precondition:
        //     fp is a pointer to a file opened for binary writing
        // Postcondition:
        //     The number of operations and the contents of the operations
        //     list have been written to fp

    void load_ops(FILE *fp);
        // Precondition:
        //     fp is a pointer to a file opened for binary reading
        // Postcondition:
        //     The number of operations and the operations to perform
        //     have been updated


    static void menu_cb(Fl_Widget *w, void *param);
        // Precondition:
        //     none
        // Postcondition:
        //     The operations list has been updated to include the selected
        //     item 

    static void button_cb(Fl_Widget *w, void *param);

    static void browser_cb(Fl_Widget *w, void *param);

    const char * generate_browser_text(IPLOP *op, int n);

    void get_op_name(Improv_Menu_Item *item, IPLOP *op);

    void get_params(IPLOP *op);

    void set_params(double p[]);

    void save_image(char *fname);
    
    void enable_enlarge();
    void disable_enlarge();

private:
    void draw();
    void process();
    void init_menu();
    int handle(int event);
    void set_focus();
};

#endif // ProcImage_h

