/*
 * A stub of the Pebble SDK, just large enough to compile src/c/main.c on a normal
 * machine so the parser can be tested against the JS writer's real output.
 *
 * NOT a simulator and not a substitute for building with the real SDK — it type-checks
 * the file and lets the wire format be verified end to end, which is the one property
 * of this app that cannot be checked by reading it. Every drawing call is a no-op.
 */
#ifndef PEBBLE_STUB_H
#define PEBBLE_STUB_H

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

typedef struct { int16_t x, y; } GPoint;
typedef struct { int16_t w, h; } GSize;
typedef struct { GPoint origin; GSize size; } GRect;
typedef struct { uint8_t argb; } GColor;
typedef struct { int16_t top, right, bottom, left; } GEdgeInsets_t;

#define GPoint(a, b) ((GPoint){ .x = (a), .y = (b) })
#define GRect(a, b, c, d) ((GRect){ .origin = { (a), (b) }, .size = { (c), (d) } })
#define GEdgeInsets(v) ((GEdgeInsets_t){ (v), (v), (v), (v) })

static inline GColor GColorFromRGB(int r, int g, int b) { (void)r; (void)g; (void)b; return (GColor){0}; }
#define GColorBlack ((GColor){0})
#define GColorWhite ((GColor){1})
#define GColorLightGray ((GColor){2})
#define GColorDarkGray ((GColor){3})
#define GColorOxfordBlue ((GColor){4})

typedef void GContext;
typedef struct Layer Layer;
typedef struct Window Window;
typedef void *ClickRecognizerRef;
typedef struct { void (*load)(Window *); void (*unload)(Window *); } WindowHandlers;

typedef enum { GTextOverflowModeFill, GTextOverflowModeWordWrap, GTextOverflowModeTrailingEllipsis } GTextOverflowMode;
typedef enum { GTextAlignmentLeft, GTextAlignmentCenter } GTextAlignment;
typedef enum { GCornerNone } GCornerMask;
typedef enum { BUTTON_ID_UP, BUTTON_ID_DOWN, BUTTON_ID_SELECT } ButtonId;
typedef enum { APP_MSG_OK = 0 } AppMessageResult;

#define FONT_KEY_GOTHIC_14_BOLD "g14b"
#define FONT_KEY_GOTHIC_18 "g18"
#define FONT_KEY_GOTHIC_24_BOLD "g24b"
typedef void *GFont;
static inline GFont fonts_get_system_font(const char *k) { (void)k; return NULL; }

typedef struct { uint32_t num_points; GPoint *points; } GPathInfo;
typedef struct { int unused; } GPath;
static inline GPath *gpath_create(GPathInfo *i) { (void)i; static GPath p; return &p; }
static inline void gpath_draw_filled(GContext *c, GPath *p) { (void)c; (void)p; }
static inline void gpath_draw_outline(GContext *c, GPath *p) { (void)c; (void)p; }
static inline void gpath_destroy(GPath *p) { (void)p; }

static inline GRect layer_get_bounds(Layer *l) { (void)l; return GRect(0, 0, 180, 180); }
static inline GRect grect_inset(GRect r, GEdgeInsets_t i) {
  r.origin.x += i.left; r.origin.y += i.top;
  r.size.w -= (i.left + i.right); r.size.h -= (i.top + i.bottom);
  return r;
}
static inline void graphics_context_set_fill_color(GContext *c, GColor g) { (void)c; (void)g; }
static inline void graphics_context_set_stroke_color(GContext *c, GColor g) { (void)c; (void)g; }
static inline void graphics_context_set_text_color(GContext *c, GColor g) { (void)c; (void)g; }
static inline void graphics_fill_rect(GContext *c, GRect r, int radius, GCornerMask m) { (void)c; (void)r; (void)radius; (void)m; }
static inline void graphics_fill_circle(GContext *c, GPoint p, int r) { (void)c; (void)p; (void)r; }
static inline void graphics_draw_circle(GContext *c, GPoint p, int r) { (void)c; (void)p; (void)r; }
static inline void graphics_draw_line(GContext *c, GPoint a, GPoint b) { (void)c; (void)a; (void)b; }
static inline void graphics_draw_text(GContext *c, const char *t, GFont f, GRect r,
                                      GTextOverflowMode o, GTextAlignment a, void *attr) {
  (void)c; (void)t; (void)f; (void)r; (void)o; (void)a; (void)attr;
}

static inline Layer *layer_create(GRect r) { (void)r; return (Layer *)malloc(1); }
static inline void layer_destroy(Layer *l) { free(l); }
static inline void layer_set_update_proc(Layer *l, void (*p)(Layer *, GContext *)) { (void)l; (void)p; }
static inline void layer_add_child(Layer *p, Layer *c) { (void)p; (void)c; }
static inline void layer_mark_dirty(Layer *l) { (void)l; }

static inline Window *window_create(void) { return (Window *)malloc(1); }
static inline void window_destroy(Window *w) { free(w); }
static inline Layer *window_get_root_layer(Window *w) { (void)w; static char l; return (Layer *)&l; }
static inline void window_set_window_handlers(Window *w, WindowHandlers h) { (void)w; (void)h; }
static inline void window_set_click_config_provider(Window *w, void (*p)(void *)) { (void)w; (void)p; }
static inline void window_stack_push(Window *w, bool a) { (void)w; (void)a; }
static inline void window_single_click_subscribe(ButtonId b, void (*h)(ClickRecognizerRef, void *)) { (void)b; (void)h; }

typedef struct { int unused; } DictionaryIterator;
typedef struct {
  int type; uint16_t length;
  union { const char *cstring; const uint8_t *data; } *value;
} Tuple;
#define TUPLE_CSTRING 1
#define TUPLE_BYTE_ARRAY 2
#define MESSAGE_KEY_PLAN 1
#define MESSAGE_KEY_STATUS 2
static inline Tuple *dict_find(DictionaryIterator *i, uint32_t k) { (void)i; (void)k; return NULL; }
static inline int dict_write_uint8(DictionaryIterator *i, uint32_t k, uint8_t v) { (void)i; (void)k; (void)v; return 0; }
static inline int app_message_outbox_begin(DictionaryIterator **i) { (void)i; return APP_MSG_OK; }
static inline int app_message_outbox_send(void) { return 0; }
static inline void app_message_register_inbox_received(void (*h)(DictionaryIterator *, void *)) { (void)h; }
static inline void app_message_register_inbox_dropped(void (*h)(AppMessageResult, void *)) { (void)h; }
static inline void app_message_open(uint32_t in, uint32_t out) { (void)in; (void)out; }

static inline bool persist_exists(uint32_t k) { (void)k; return false; }
static inline int persist_read_data(uint32_t k, void *b, size_t s) { (void)k; (void)b; (void)s; return 0; }
static inline int persist_write_data(uint32_t k, const void *b, size_t s) { (void)k; (void)b; (void)s; return (int)s; }

static inline void app_event_loop(void) {}

#endif
