/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>
#include <sys/types.h>

#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <cutils/memory.h>
#include <asm-generic/mman.h>
#include <sys/mman.h>
#include <utils/threads.h>
#include <unistd.h>
#include <math.h>

using namespace android;

#ifndef FBIO_WAITFORVSYNC
#define FBIO_WAITFORVSYNC   _IOW('F', 0x20, __u32)
#endif

struct Buffer {
    size_t w;
    size_t h;
    size_t s;
    union {
        void* addr;
        uint32_t* pixels;
    };
};

void clearBuffer(Buffer* buf, uint32_t pixel) {
    android_memset32(buf->pixels, pixel, buf->s * buf->h * 4);
}

void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
    if (y>0 && y<ssize_t(buf->h)) {
        uint32_t* bits = buf->pixels + y * buf->s;
        if (x>=0 && x<buf->w) {
            bits[x] = pixel;
        }
        ssize_t W(w);
        if ((x+W)>=0 && (x+W)<buf->w) {
            bits[x+W] = pixel;
        }
    }
}

void drawHLine(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
    if (y>0 && y<ssize_t(buf->h)) {
        ssize_t W(w);
        if (x<0) {
            W += x;
            x = 0;
        }
        if (x+w > buf->w) {
            W = buf->w - x;
        }
        if (W>0) {
            uint32_t* bits = buf->pixels + y * buf->s + x;
            android_memset32(bits, pixel, W*4);
        }
    }
}

void drawRect(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w, size_t h) {
    ssize_t W(w), H(h);
    if (x<0) {
        w += x;
        x = 0;
    }
    if (y<0) {
        h += y;
        y = 0;
    }
    if (x+w > buf->w)   W = buf->w - x;
    if (y+h > buf->h)   H = buf->h - y;
    if (W>0 && H>0) {
        uint32_t* bits = buf->pixels + y * buf->s + x;
        for (ssize_t i=0 ; i<H ; i++) {
            android_memset32(bits, pixel, W*4);
            bits += buf->s;
        }
    }
}

void drawCircle(Buffer* buf, uint32_t pixel,
        size_t x0, size_t y0, size_t radius, bool filled = false) {
    ssize_t f = 1 - radius;
    ssize_t ddF_x = 1;
    ssize_t ddF_y = -2 * radius;
    ssize_t x = 0;
    ssize_t y = radius;
    if (filled) {
        drawHLine(buf, pixel, x0-radius, y0, 2*radius);
    } else {
        drawTwoPixels(buf, pixel, x0-radius, y0, 2*radius);
    }
    while (x < y) {
        if (f >= 0) {
            y--;
            ddF_y += 2;
            f += ddF_y;
        }
        x++;
        ddF_x += 2;
        f += ddF_x;
        if (filled) {
            drawHLine(buf, pixel, x0-x, y0+y, 2*x);
            drawHLine(buf, pixel, x0-x, y0-y, 2*x);
            drawHLine(buf, pixel, x0-y, y0+x, 2*y);
            drawHLine(buf, pixel, x0-y, y0-x, 2*y);
        } else {
            drawTwoPixels(buf, pixel, x0-x, y0+y, 2*x);
            drawTwoPixels(buf, pixel, x0-x, y0-y, 2*x);
            drawTwoPixels(buf, pixel, x0-y, y0+x, 2*y);
            drawTwoPixels(buf, pixel, x0-y, y0-x, 2*y);
        }
    }
}

class TouchEvents {
    class EventThread : public Thread {
        int fd;

        virtual bool threadLoop() {
            input_event event;
            int first_down = 0;
            do {
                read(fd, &event, sizeof(event));
                if (event.type == EV_ABS) {
                    if (event.code == ABS_MT_TRACKING_ID) {
                        down = event.value == -1 ? 0 : 1;
                        first_down = down;
                    }
                    if (event.code == ABS_MT_POSITION_X) {
                        x = event.value;
                    }
                    if (event.code == ABS_MT_POSITION_Y) {
                        y = event.value;
                    }
                }
            } while (event.type == EV_SYN);
            return true;
        }

    public:
        int x, y, down;
        EventThread() : Thread(false),
                x(0), y(0), down(0)
        {
            fd = open("/dev/input/event1", O_RDONLY);
        }
};
    sp<EventThread> thread;

public:
    TouchEvents() {
        thread = new EventThread();
        thread->run("EventThread", PRIORITY_URGENT_DISPLAY);
    }

    int getMostRecentPosition(int* x, int* y) {
        *x = thread->x;
        *y = thread->y;
        return thread->down;
    }
};


struct Queue {
    struct position {
        int x, y;
    };
    int index;
    position q[16];
    Queue() : index(0) { }
    void push(int x, int y) {
        index++;
        index &= 0xF;
        q[index].x = x;
        q[index].y = y;
    }
    void get(int lag, int* x, int* y) {
        const int i = (index - lag) & 0xF;
        *x = q[i].x;
        *y = q[i].y;
    }
};

extern char *optarg;
extern int optind;
extern int optopt;
extern int opterr;
extern int optreset;

void usage(const char* name) {
    printf("\nusage: %s [-h] [-l lag]\n", name);
}

int main(int argc, char** argv) {
    fb_var_screeninfo vi;
    fb_fix_screeninfo fi;

    int lag = 0;
    int fd = open("/dev/graphics/fb0", O_RDWR);
    ioctl(fd, FBIOGET_VSCREENINFO, &vi);
    ioctl(fd, FBIOGET_FSCREENINFO, &fi);
    void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    Buffer framebuffer;
    framebuffer.w = vi.xres;
    framebuffer.h = vi.yres;
    framebuffer.s = fi.line_length / (vi.bits_per_pixel >> 3);
    framebuffer.addr = bits;

    int ch;
    while ((ch = getopt(argc, argv, "hl:")) != -1) {
        switch (ch) {
            case 'l':
                lag = atoi(optarg);
                break;
            case 'h':
            default:
                usage(argv[0]);
                exit(0);
        }
    }
    argc -= optind;
    argv += optind;


    TouchEvents touch;
    Queue queue;


    int x=0, y=0, down=0;
    int lag_x=0, lag_y=0;

    clearBuffer(&framebuffer, 0);
    while (true) {
        uint32_t crt = 0;
        int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt);

        // draw beam marker
        drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h);
        // erase screen
        if (lag) {
            drawCircle(&framebuffer, 0, lag_x, lag_y, 100);
            drawHLine(&framebuffer, 0, 0, lag_y, 32);
        }
        drawCircle(&framebuffer, 0, x, y, 100, true);
        drawHLine(&framebuffer, 0, 0, y, 32);

        // draw a line at y=1000
        drawHLine(&framebuffer, 0x808080, 0, 1000, framebuffer.w);

        // get touch events
        touch.getMostRecentPosition(&x, &y);
        queue.push(x, y);
        queue.get(lag, &lag_x, &lag_y);

        if (lag) {
            drawCircle(&framebuffer, 0x00FF00, lag_x, lag_y, 100);
            drawHLine(&framebuffer, 0x00FF00, 0, lag_y, 32);
        }

        drawCircle(&framebuffer, 0xFFFFFF, x, y, 100, true);
        drawHLine(&framebuffer, 0xFFFFFF, 0, y, 32);

        // draw end of frame beam marker
        drawRect(&framebuffer, 0x004000, framebuffer.w-2, 0, 2, framebuffer.h);
    }

    close(fd);
    return 0;
}
