use ui;
use core:geometry;


/**
 * A slide intro animation. Used to define slide transitions.
 *
 * If 'duration' is zero when the animation is added to the presentation, the presentation will
 * overwrite the duration with its default setting.
 */
class SlideIntro on Render {
	// Duration of the animation.
	Duration duration;

	// Create, default duration.
	init() {
		init() {}
	}

	// Create.
	init(Duration d) {
		init() {
			duration = d;
		}
	}

	// Draw the animation.
	void draw(Presentation p, Graphics g, Presentation:Cursor pos, Presentation:Cursor? last, Duration time) : abstract;

	// Convert a time into a float in the range 0..1.
	package Float val(Duration d) {
		clamp(d / duration, 0.0, 1.0);
	}
}


/**
 * A simple crossfade.
 */
class FadeInIntro extends SlideIntro {
	// Create.
	init() {
		init() {}
	}

	// Create.
	init(Duration d) {
		init(d) {}
	}

	// Draw the animation.
	void draw(Presentation p, Graphics g, Presentation:Cursor pos, Presentation:Cursor? last, Duration time) : override {
		if (last)
			p.drawSlide(g, last);

		g.push(val(time));
		p.drawSlide(g, pos, time);
		g.pop();
	}
}


/**
 * Slide the old slide down.
 */
class SlideDownIntro extends SlideIntro {
	// Should we fade as well?
	Bool fade;

	// Create.
	init(Bool fade) { init() { fade = fade; } }

	// Create.
	init(Duration d, Bool fade) { init(d) { fade = fade; } }

	// Draw!
	void draw(Presentation p, Graphics g, Presentation:Cursor pos, Presentation:Cursor? last, Duration time) : override {
		p.drawSlide(g, pos, time);

		if (last) {
			// Get some acceleration!
			var t = pow(val(time), 2);

			if (fade) {
				g.push(1.0 - t);
			} else {
				g.push();
			}
			g.transform = translate(Size(0, t * p.size.h));
			p.drawSlide(g, last);
			g.pop();
		}
	}
}


/**
 * Enlarge the old slide and fade it out.
 */
class EnlargeIntro extends SlideIntro {
	// Create.
	init() { init() {} }
	init(Duration d) { init() {} }

	// Draw!
	void draw(Presentation p, Graphics g, Presentation:Cursor pos, Presentation:Cursor? last, Duration time) : override {
		p.drawSlide(g, pos, time);

		if (last) {
			var t = val(time);
			Point center = p.size / 2;
			g.push(1.0 - t);
			g.transform = scale(1.0 + t * t * 4, center);
			p.drawSlide(g, last);
			g.pop();
		}
	}
}
