/**
 * nullanvoid :: bitjammin
 * A simple C program to influence the backlight.
 * This was written for the Dell XPS 9315
 */

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
#include <unistd.h>
#include "backlight.h"

#define BL_BRIGHTNESS "/sys/class/backlight/intel_backlight/brightness"
#define BL_MAX_BRIGHTNESS "/sys/class/backlight/intel_backlight/max_brightness"
#define ADJUST_AMOUNT 500

void
usage ()
{
  fprintf (stdout, "Usage: backlight [options]\n"
	   "Options:\n"
	   "    -d         Decrement brightness by %d\n"
	   "    -i         Increment brightness by %d\n"
	   "    -s value   Set brightness to arbitrary value (MAX BRIGHTNESS = %d)\n"
	   "    -v         Print the new brightness value to stdout\n"
	   "               read from %s\n",
	   ADJUST_AMOUNT, ADJUST_AMOUNT, get_max_brightness (), BL_BRIGHTNESS);
  exit (1);
}


int
get_max_brightness ()
{
  FILE *fp;
  int maximum;
  if ((fp = fopen (BL_MAX_BRIGHTNESS, "r")) == NULL)
    {
      printf ("Unable to read max brightness.\n");
      exit (1);
    }

  fscanf (fp, "%d", &maximum);
  fclose (fp);

  return maximum;
}


int
set_brightness (int brightness, int value)
{
  FILE *fp;
  int curr_brightness;
  int new_brightness;

  if ((fp = fopen (BL_BRIGHTNESS, "r+")) == NULL)
    {
      printf ("Unable to read brightness from backlight\n");
      exit (1);
    }

  fscanf (fp, "%d", &curr_brightness);

  if (value >= 0)
    {
      new_brightness = value;
    }
  else if (brightness < 0)
    {
      if ((new_brightness = curr_brightness - ADJUST_AMOUNT) < 0)
	new_brightness = 0;
    }
  else if (brightness > 0)
    {
      new_brightness = curr_brightness + ADJUST_AMOUNT;
    }

  fprintf (fp, "%d", new_brightness);
  fseek (fp, 0, SEEK_SET);
  fscanf (fp, "%d", &curr_brightness);
  fclose (fp);

  return curr_brightness;
}


int
main (int argc, char **argv)
{
  int c;
  int brightness = 0;
  int set_value = -1;
  int verbose = 0;

  while ((c = getopt (argc, argv, "dhis:v")) != -1)
    switch (c)
      {
      case 'd':
	brightness--;
	break;
      case 'h':
	usage ();
	break;
      case 'i':
	brightness++;
	break;
      case 's':
	set_value = atoi (optarg);
	break;
      case 'v':
        verbose = 1;
	break;
      case '?':
	if (isprint (optopt))
	  fprintf (stderr, "Unknown option `-%c'.\n", optopt);
	else
	  fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
	return 1;
      default:
	usage ();;
      }

  if (brightness == 0 && set_value < 0)
    {
      usage ();
    }


  if ((brightness = set_brightness (brightness, set_value)) < 0)
    {
      fprintf (stderr, "hrm, interesting\n");
    }
  else if (verbose)
    {
      fprintf(stdout, "Backlight brightness set to: %d\n", brightness);
    }

  return 0;
}