/*
██████╗░░█████╗░████████╗████████╗░░░░░░░██████╗██╗░██████╗░███╗░░██╗░█████╗░██╗░░░░░
██╔══██╗██╔══██╗╚══██╔══╝╚══██╔══╝░░░░░░██╔════╝██║██╔════╝░████╗░██║██╔══██╗██║░░░░░
██████╦╝███████║░░░██║░░░░░░██║░░░█████╗╚█████╗░██║██║░░██╗░██╔██╗██║███████║██║░░░░░
██╔══██╗██╔══██║░░░██║░░░░░░██║░░░╚════╝░╚═══██╗██║██║░░╚██╗██║╚████║██╔══██║██║░░░░░
██████╦╝██║░░██║░░░██║░░░░░░██║░░░░░░░░░██████╔╝██║╚██████╔╝██║░╚███║██║░░██║███████╗
╚═════╝░╚═╝░░╚═╝░░░╚═╝░░░░░░╚═╝░░░░░░░░░╚═════╝░╚═╝░╚═════╝░╚═╝░░╚══╝╚═╝░░╚═╝╚══════╝
*/

#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/xf86vmode.h>
#include <X11/keysym.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#define FONT_SIZE 24



typedef struct {
  unsigned long flags;
  unsigned long functions;
  unsigned long decorations;
  long          inputMode;
  unsigned long status;
} Hints;




int width, height;
char *message = "Battery is low!!";




void catch_fire(char *, int);
void draw_ui(Display *, Window, Visual *, Colormap, int);
void window_attr(Display *, Window, int);
void alert();


enum state {
  Alert,
  Normal
};


int main(void) {

  time_t lastalert = 0; // a long time ago
  enum state laststate = Normal, curstate = Normal;


  while (1) {
    FILE *battery = fopen("/sys/class/power_supply/BAT0/capacity","r");
    FILE *status  = fopen("/sys/class/power_supply/BAT0/status","r");
  if(battery == NULL || status == NULL) {
    catch_fire("batt-signal : Cannot find battery.\n", 100);
  }


      int cap;
      char bat_status[20] = "";

      fscanf(battery,"%d", &cap);
      fscanf(status, "%s", bat_status);

      curstate = cap <= 15 && strcmp(bat_status, "Discharging") == 0 ? Alert : Normal;
      if (curstate == Alert && (time(NULL) - lastalert >= 180 || laststate == Normal)) {
        alert();
        lastalert = time(NULL);
      }
      laststate = curstate;
printf("%s : %d\n", bat_status, cap);

    fclose(battery);
    fclose(status);
    sleep(1);
  }


  return 0;
}






void catch_fire(char *string, int error) {
  fprintf(stderr, string);
  exit(error);
}





void draw_ui(Display *d, Window w, Visual *visual, Colormap cmap, int s) {

  // FONT SHENANIGANS
  char font_name[strlen("monospace-") + 2];
  sprintf(font_name, "monospace-%d", FONT_SIZE);
  XftFont *font = XftFontOpenName(d, s, font_name);

  printf("lol1\n");
  // FONT COLORS
  XftColor xft_black, xft_white;
  XftColorAllocName(d, visual, cmap, "black", &xft_black);
  XftColorAllocName(d, visual, cmap, "white", &xft_white);

  XftDraw *xftdraw = XftDrawCreate(d, w, visual, cmap);



  // MAKE WHITE RECT
  int white_rect_x      = width  / 24;
  int white_rect_y      = height / 12;
  int white_rect_width  = width  / 18;
  int white_rect_height = height / 6;

  XftDrawRect(xftdraw, &xft_white, white_rect_x, white_rect_y, white_rect_width, white_rect_height);



  // MAKE BLACK RECT
  int black_rect_x      = width  / 24 + width  / 140;
  int black_rect_y      = height / 12 + height / 100;
  int black_rect_width  = width  / 24;
  int black_rect_height = height / 8;

  XftDrawRect(xftdraw, &xft_black, black_rect_x, black_rect_y, black_rect_width, black_rect_height);



  // MAKE WHITE BAR
  int bar_rect_x      = width  / 24 + width  / 36 - width / 120;
  int bar_rect_y      = height / 12 - height / 100;
  int bar_rect_width  = width  / 60;
  int bar_rect_height = height / 60;

  XftDrawRect(xftdraw, &xft_white, bar_rect_x, bar_rect_y, bar_rect_width, bar_rect_height);


  // PRINT PASS MESSAGE
  XftDrawString8(xftdraw, &xft_white, font, white_rect_x *3, height/6, message, strlen(message));


}

void alert()
  {
    Display *d = XOpenDisplay(NULL);
    if (d == NULL)
      catch_fire("Cannot open display\n", 1);

    int s     = DefaultScreen(d);
    int depth = DefaultDepth(d, s);
    width     = DisplayWidth(d, s);
    height    = DisplayHeight(d, s);

    Window w;
    Visual *visual = DefaultVisual(d, s);
    Colormap cmap  = DefaultColormap(d, s);



    // IGNORES WM RULES
    XSetWindowAttributes attributes;
    attributes.override_redirect = True;
    attributes.background_pixel  = BlackPixel(d, s);


    // MAKE THE WINDOW
    w = XCreateWindow(d, XRootWindow(d, s), 0, 0, width, height, 0, depth, InputOutput, visual, CWBackPixel | CWOverrideRedirect, &attributes);


    // SET WINDOW ATTRIBUTES
    window_attr(d, w, s);

    // DRAW THE RECTANGLES AND STRINGS
    draw_ui(d, w, visual, cmap, s);



    //PLAY THE SOUND
    pid_t child_id;

    child_id = fork();

    if (child_id == -1) {
      catch_fire("Couldn't fork\n", 1);
    } else if (child_id == 0) {
      execl("/usr/bin/mpg123", "mpg123",  SHAREPREFIX "/lobat.mp3", NULL);
    }

    while (1) {

      int foo;
      KeySym ksym;
      XEvent e;

      XNextEvent(d, &e);

      // CHECK IF ANYTHING IS PRESSED
      if(e.type == KeyPress)
        break;

      draw_ui(d, w, visual, cmap, s);
    }

    XCloseDisplay(d);
  }

void window_attr(Display *d, Window w, int s) {

  int mode_count;

  // VIDEO  MODES
  XF86VidModeModeInfo **modes, *video_mode;
  XF86VidModeGetAllModeLines(d, s, &mode_count, &modes);
  video_mode = modes[0];

  // DISABLE DECORATIONS
  Hints hints;
  hints.flags = 2;
  hints.decorations = 0;

  Atom roperty = XInternAtom(d, "_MOTIF_WM_HINTS", True);

  XSelectInput(d, w, ExposureMask | KeyPressMask);
  XMapWindow(d, w);

  // SETTING FULLSCREEN
  XF86VidModeSwitchToMode(d, s, video_mode);
  XF86VidModeSetViewPort(d, s, 0, 0);
  XMoveResizeWindow(d, w, width/3, height/3, width/3, height/3);
  XMapRaised(d, w);

  XGrabPointer(d, w, True, 0, GrabModeAsync, GrabModeAsync, w, 0L, CurrentTime);
  XGrabKeyboard(d, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);

}
