#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include <frame.h>
#include <fcall.h>
#include "dat.h"
#include "fns.h"

static Image *scrtmp;

static
void
scrtemps(void)
{
	int h;

	if(scrtmp)
		return;
	h = BIG*Dy(screen->r);
	scrtmp = allocimage(display, Rect(0, 0, 32, h), screen->chan, 0, DWhite);
	if(scrtmp == nil)
		error("scrtemps");
}

void
freescrtemps(void)
{
	freeimage(scrtmp);
	scrtmp = nil;
}

static
Rectangle
scrpos(Rectangle r, uint p0, uint p1, uint tot)
{
	Rectangle q;
	int h;

	q = r;
	h = q.max.y-q.min.y;
	if(tot == 0)
		return q;
	if(tot > 1024*1024){
		tot>>=10;
		p0>>=10;
		p1>>=10;
	}
	if(p0 > 0)
		q.min.y += h*p0/tot;
	if(p1 < tot)
		q.max.y -= h*(tot-p1)/tot;
	if(q.max.y < q.min.y+2){
		if(q.min.y+2 <= r.max.y)
			q.max.y = q.min.y+2;
		else
			q.min.y = q.max.y-2;
	}
	return q;
}

void
wscrdraw(Window *w)
{
	Rectangle r, r1, r2;
	Image *b;

	scrtemps();
	if(w->i == nil)
		error("scrdraw");
	r = w->scrollr;
	b = scrtmp;
	r1 = r;
	r1.min.x = 0;
	r1.max.x = Dx(r);
	r2 = scrpos(r1, w->org, w->org+w->f.nchars, w->nr);
	if(!eqrect(r2, w->lastsr)){
		w->lastsr = r2;
		/* move r1, r2 to (0,0) to avoid clipping */
		r2 = rectsubpt(r2, r1.min);
		r1 = rectsubpt(r1, r1.min);
		draw(b, r1, w->f.cols[BORD], nil, ZP);
		draw(b, r2, w->f.cols[BACK], nil, ZP);
		r2.min.x = r2.max.x-1;
		draw(b, r2, w->f.cols[BORD], nil, ZP);
		draw(w->i, r, b, nil, Pt(0, r1.min.y));
	}
}

void
wscrsleep(Window *w, uint dt)
{
	Timer	*timer;
	int y, b;
	static Alt alts[3];

	timer = timerstart(dt);
	y = w->mc.m.xy.y;
	b = w->mc.m.buttons;
	alts[0].c = timer->c;
	alts[0].v = nil;
	alts[0].op = CHANRCV;
	alts[1].c = w->mc.c;
	alts[1].v = &w->mc.m;
	alts[1].op = CHANRCV;
	alts[2].op = CHANEND;
	for(;;)
		switch(alt(alts)){
		case 0:
			timerstop(timer);
			return;
		case 1:
			if(abs(w->mc.m.xy.y-y)>2 || w->mc.m.buttons!=b){
				timercancel(timer);
				return;
			}
			break;
		}
}

void
wscroll(Window *w, int but)
{
	uint p0, oldp0;
	Rectangle s;
	int x, y, my, h, first;

	s = insetrect(w->scrollr, 1);
	h = s.max.y-s.min.y;
	x = (s.min.x+s.max.x)/2;
	oldp0 = ~0;
	first = TRUE;
	do{
		flushimage(display, 1);
		if(w->mc.m.xy.x<s.min.x || s.max.x<=w->mc.m.xy.x){
			readmouse(&w->mc);
		}else{
			my = w->mc.m.xy.y;
			if(my < s.min.y)
				my = s.min.y;
			if(my >= s.max.y)
				my = s.max.y;
			if(!eqpt(w->mc.m.xy, Pt(x, my))){
				wmovemouse(w, Pt(x, my));
				readmouse(&w->mc);		/* absorb event generated by moveto() */
			}
			if(but == 2){
				y = my;
				if(y > s.max.y-2)
					y = s.max.y-2;
				if(w->nr > 1024*1024)
					p0 = ((w->nr>>10)*(y-s.min.y)/h)<<10;
				else
					p0 = w->nr*(y-s.min.y)/h;
				if(oldp0 != p0)
					wsetorigin(w, p0, FALSE);
				oldp0 = p0;
				readmouse(&w->mc);
				continue;
			}
			if(but == 1)
				p0 = wbacknl(w, w->org, (my-s.min.y)/w->f.font->height);
			else
				p0 = w->org+frcharofpt(&w->f, Pt(s.max.x, my));
			if(oldp0 != p0)
				wsetorigin(w, p0, TRUE);
			oldp0 = p0;
			/* debounce */
			if(first){
				flushimage(display, 1);
				sleep(200);
				nbrecv(w->mc.c, &w->mc.m);
				first = FALSE;
			}
			wscrsleep(w, 100);
		}
	}while(w->mc.m.buttons & (1<<(but-1)));
	while(w->mc.m.buttons)
		readmouse(&w->mc);
}
