#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#define BASEPATH "/sys/class/gpio/"
#define GPIO_FOLDER "gpio%s/"

#define PIN_BUTTON "17"
#define PIN_LED "18"

#define LED_ON 0
#define LED_OFF 1

#define BUTTON_PRESSED 0
#define BUTTON_RELEASED 1

void writeFile(char *filename, char *buffer, size_t count)
{
    int fd = open(filename, O_WRONLY);
    write(fd, buffer, count);
    close(fd);
}

void registerPin(char *pin)
{
    writeFile(BASEPATH "export", pin, strlen(pin));
}

void freePin(char *pin)
{
    writeFile(BASEPATH "unexport", pin, strlen(pin));
}

void setDirection(char *pin, char *direction, int dirlen)
{
    char path[50];
    sprintf(path, BASEPATH GPIO_FOLDER "direction", pin);
    writeFile(path, direction, dirlen);
}

void registerInput(char *pin)
{
    registerPin(pin);
    setDirection(pin, "in", 2);
}

void registerOutput(char *pin)
{
    registerPin(pin);
    setDirection(pin, "out", 3);
}

int readInput(char *pin)
{
    char path[50];
    int state;
    sprintf(path, BASEPATH GPIO_FOLDER "value", pin);
    FILE *fd = fopen(path, "r");
    fscanf(fd, "%i", &state);
    fclose(fd);
    return state;
}

void writeOutput(char *pin, int state)
{
    char path[50];
    sprintf(path, BASEPATH GPIO_FOLDER "value", pin);
    FILE *fd = fopen(path, "w");
    fprintf(fd, "%i", state);
    fclose(fd);
}

int main()
{
    struct timespec sleeptime, sleepremain;
    int oldstate = BUTTON_PRESSED;
    int state;
    int count = 0;
    registerInput(PIN_BUTTON);
    registerOutput(PIN_LED);
    sleeptime.tv_sec = 0;
    sleeptime.tv_nsec = 1000000;
    while (1)
    {
        nanosleep(&sleeptime, &sleepremain);
        state = readInput(PIN_BUTTON);
        if (state == BUTTON_PRESSED && oldstate == BUTTON_RELEASED)
        {
            count++;
            printf("Number of button pushes: %i\n", count);
        }

        if (state == BUTTON_PRESSED)
            writeOutput(PIN_LED, LED_ON);
        else
            writeOutput(PIN_LED, LED_OFF);

        oldstate = state;
    }
}
