/* This file just lists some ideas for the future... I'll keep it for now. */


/* Configuration */
#define CFG_BUF_SIZE    4096
#define CFG_MAX_ITEMS   256
#define CFG_MAX_CALIBS  16

#include "ring_buf.h"
#include "fd.h"

/* Description of an item type. */
struct item_info {
    /* 32-bit globally-recognized product identifier. */
    long id;

    /* Self-explanatory. */
    char* name;

    /* I suppose this acts as a placeholder for more structured information.
     * Actually expanding this to a full struct is a project in itself. */
    char* description;

    /* Typical mass of the container.  Before calculating volume, this is
     * subtracted from the item's mass. */
    int container_mass;

    /* Grams per liter. */
    double density;

    /* More ideas:
     *
     * - Substitution information, something along the lines of "a Persian lime
     *   counts as two and a half Key limes."  Or maybe "Ro-Tel consists of
     *   diced green chilis and tomatos."
     *
     * - Nutrition facts, including serving size.
     *
     * - Unit information.  Different kinds of foods are conventionally
     *   measured in different ways.  For now just use liters.
     *
     * - Cross-reference with recipe list.  This would only be a speed
     *   optimization, I think.
     *
     * - Quantity on-hand.  Again, an optimization.
     *
     * - Price and other purchase information.  In the future it might be kind
     *   of neat for Smartshelf to generate shopping lists and maybe even
     *   place orders for food to be delivered or picked up at a grocery store.
     *
     * - Typical initial mass and volume.  This can be used to determine if the
     *   box/jar has been opened yet and also to help identify bogus values.
     *
     * - Pictures for the GUI to display to help the user locate the item.
     *
     * - Shelf life before and after opening container.
     *
     * - Footprint.  I'm not sure how this would be useful, but it's an idea.
     *
     * - User preferences inferred from history.  As an example, Smartshelf can
     *   observe that this food is consumed at a high rate, and therefore it'll
     *   suggest that it be purchased in larger quantity.
     *
     * - Categorization information.  For instance, a food can be marked as
     *   salty, and if Smartshelf observes that the user doesn't much care for
     *   the taste, then recipes can be adjusted, alternatives suggested, etc.
     *
     * - Much is possible... */
} item_info_t;

/* Single item on a shelf. */
struct item {
    /* Product identifier, stored as the low 32 bits of the RFID tag. */
    long id;

    /* The high 32 bits of the RFID tag.  For now let's call it an expiration
     * date, format to be determined.  Or maybe it should be the date of
     * production, if shelf life information is available.
     *
     * Gee, is it important that separate items of the same type have separate
     * tags?  Yeah, I think so, since otherwise adding a new item of a type
     * already present on the shelf might cause it to not be counted.  If
     * there are multiple tags with the same value, will the RFID reader
     * separately report all instances?  When removing an item of which there
     * are several on the shelf, the specific item can be determined by
     * watching how much weight was lifted.
     *
     * Let's think about it some more... */
    long expiration;

    /* Pointer to the corresponding item_info.  This is an optimization to
     * avoid repeated lookups by id.  If we store item_info objects in a
     * balanced tree and efficiency is good enough, this can be dropped. */
    item_info_t* info;

    /* Estimated position on the shelf.  These numbers can be multiplied by the
     * shelf's dimensions to get an actual physical location, but for now it's
     * not strictly necessary. */
    struct {double x, y;} position;

    /* Estimated mass in grams.  To get the volume in liters, subtract the
     * container's mass and then divide by the item's density. */
    int mass;
} item_t;

/* A smart shelf! */
struct shelf {
    /* What's on the shelf?? */
    item_t items[CFG_MAX_ITEMS];
    int num_items;

    /* Maybe store the dimensions of the shelf. */
} shelf_t;

/* List of serial ports. */
/* extern serial_t ports[2]; */

/* Evaluates to the lesser of the two operands. */
#define MIN(a, b) ({typeof(a) _a = (a); typeof(b) _b = (b); \
                    _a < _b ? _a : _b;})

/* Evaluates to the greater of the two operands. */
#define MAX(a, b) ({typeof(a) _a = (a); typeof(b) _b = (b); \
                    _a > _b ? _a : _b;})

/* Evaluates to the number of elements in an array. */
#define LEN(x) (sizeof(x) / sizeof(*(x)))

/* Connection to a client monitoring the hardware.
 *
 * Okay, so what's the division of responsibility between this program and the
 * client?  At the moment I think it would be best to make this program very
 * powerful and keep the client lightweight.  All the databases and artificial
 * intelligence should stay here, and the client's main responsibility is
 * interfacing with the user. */
typedef struct client {
    FD_STRUCT;                      /* Inherit parent struct's fields. */

    int for_xmit;                   /* True if connected to stdout. */
    int for_recv;                   /* True if connected to stdin. */

    /* Probably more stuff goes here... */
} client_t;

/* State information for a Texas Instruments RFID tag reader. */
typedef struct rfid_reader {
    long long tags[CFG_MAX_ITEMS];  /* List of tags. */
    int num_tags;                   /* Number of tags in reader's range. */

    int packet_rem;                 /* Bytes remaining until end of packet. */

    shelf_t* shelf;                 /* Associated shelf. */
} rfid_reader_t;

/* State information for a pressure sensor device.  The current pressure sensor
 * consists of four physical sensors and two magnetic reed switches. */
typedef struct pressure {
    struct calib {                  /* A calibration sample. */
        int val;                    /* Value read from sensor. */
        float mass;                 /* Mass placed on that sensor. */
    } calibs[CFG_MAX_CALIBS][4];    /* List of samples, for each sensor. */
    int num_calibs;                 /* Number of calibration samples. */

    int door_status;                /* True if the door is opened. */

    int have_sync;                  /* Currently in sync with device? */
    int packet_rem;                 /* Bytes remaining until end of packet. */
    int packet_len;                 /* Number of bytes in a good packet. */
    int packet_bad;                 /* If true, current packet is bad. */

    shelf_t* shelf;                 /* Associated shelf. */
} pressure_t;

/* vim: set syn=c: */
