/*
 * Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include "dbus_interface.h"
#include "image.h"
#include "input.h"
#include "splash.h"
#include "term.h"
#include "util.h"

#define  MAX_SPLASH_IMAGES      (30)
#define  MAX_SPLASH_WAITTIME    (8)
#define  DBUS_WAIT_DELAY        (50000)

typedef struct {
	image_t    *image;
	uint32_t    duration;
} splash_frame_t;

struct _splash_t {
	video_t         *video;
	terminal_t      *terminal;
	int              num_images;
	uint32_t         clear;
	splash_frame_t   image_frames[MAX_SPLASH_IMAGES];
	bool             terminated;
	bool             devmode;
	dbus_t          *dbus;
	int32_t          loop_start;
	uint32_t         loop_duration;
	uint32_t         default_duration;
	int32_t          offset_x;
	int32_t          offset_y;
	int32_t          loop_offset_x;
	int32_t          loop_offset_y;
};


splash_t* splash_init()
{
	splash_t* splash;
	FILE *cookie_fp;

	splash = (splash_t*)calloc(1, sizeof(splash_t));
	if (splash == NULL)
		return NULL;

	splash->video = video_init();
	splash->terminal = input_create_splash_term(splash->video);
	splash->loop_start = -1;
	splash->default_duration = 25;
	splash->loop_duration = 25;

	// Hide the cursor on the splash screen
	term_hide_cursor(splash->terminal);

	cookie_fp = fopen("/tmp/display_info.bin", "wb");
	if (cookie_fp) {
		fwrite(&splash->video->internal_panel, sizeof(char), 1, cookie_fp);
		fwrite(splash->video->edid, EDID_SIZE, 1, cookie_fp);
		fclose(cookie_fp);
	}

	return splash;
}

int splash_destroy(splash_t* splash)
{
	if (splash->terminal) {
		term_close(splash->terminal);
		splash->terminal = NULL;
	}
	free(splash);
	input_destroy_splash_term();
	return 0;
}

int splash_set_clear(splash_t *splash, uint32_t clear_color)
{
	splash->clear = clear_color;
	return 0;
}

int splash_add_image(splash_t* splash, char* filespec)
{
	image_t* image;
	int32_t offset_x, offset_y;
	char *filename;
	uint32_t duration;
	if (splash->num_images >= MAX_SPLASH_IMAGES)
		return 1;

	filename = (char*)malloc(strlen(filespec) + 1);
	parse_filespec(filespec,
			filename,
			&offset_x, &offset_y, &duration,
			splash->default_duration,
			splash->offset_x,
			splash->offset_y);

	image = image_create();
	image_set_filename(image, filename);
	image_set_offset(image, offset_x, offset_y);
	splash->image_frames[splash->num_images].image = image;
	splash->image_frames[splash->num_images].duration = duration;
	splash->num_images++;

	free(filename);
	return 0;
}

static void splash_clear_screen(splash_t *splash)
{
	term_set_background(splash->terminal, splash->clear);
}

int splash_run(splash_t* splash, dbus_t** dbus)
{
	int i;
	int status;
	int64_t last_show_ms;
	int64_t now_ms;
	int64_t sleep_ms;
	struct timespec sleep_spec;
	int fd;
	int num_written;
	image_t* image;
	uint32_t duration;

	/*
	 * First draw the actual splash screen
	 */
	splash_clear_screen(splash);
	term_activate(splash->terminal);
	last_show_ms = -1;
	for (i = 0; i < splash->num_images; i++) {
		image = splash->image_frames[i].image;
		status = image_load_image_from_file(image);
		if (status != 0) {
			LOG(WARNING, "image_load_image_from_file failed: %d", status);
			break;
		}

		now_ms = get_monotonic_time_ms();
		if (last_show_ms > 0) {
			if (splash->loop_start >= 0 && i >= splash->loop_start)
				duration = splash->loop_duration;
			else
				duration = splash->image_frames[i].duration;
			sleep_ms = duration - (now_ms - last_show_ms);
			if (sleep_ms > 0) {
				sleep_spec.tv_sec = sleep_ms / MS_PER_SEC;
				sleep_spec.tv_nsec = (sleep_ms % MS_PER_SEC) * NS_PER_MS;
				nanosleep(&sleep_spec, NULL);
			}
		}

		now_ms = get_monotonic_time_ms();

		if (i >= splash->loop_start) {
			image_set_offset(image,
					splash->loop_offset_x,
					splash->loop_offset_y);
		}

		status = term_show_image(splash->terminal, image);
		if (status != 0) {
			LOG(WARNING, "term_show_image failed: %d", status);
			break;
		}
		status = input_process(splash->terminal, 1);
		if (status != 0) {
			LOG(WARNING, "input_process failed: %d", status);
			break;
		}
		last_show_ms = now_ms;

		if ((splash->loop_start >= 0) &&
				(splash->loop_start < splash->num_images)) {
			if (i == splash->num_images - 1)
				i = splash->loop_start - 1;
		}

		image_release(image);
	}

	for (i = 0; i < splash->num_images; i++) {
		image_destroy(splash->image_frames[i].image);
	}

	input_set_current(NULL);
	input_ungrab();

	/*
	 * Now Chrome can take over
	 */
	video_release(splash->video);
	video_unlock(splash->video);

	if (dbus != NULL) {
		do {
			*dbus = dbus_init();
			usleep(DBUS_WAIT_DELAY);
		} while (*dbus == NULL);
		splash_set_dbus(splash, *dbus);
	}

	if (splash->devmode) {
		/*
		 * Now set drm_master_relax so that we can transfer drm_master between
		 * chrome and frecon
		 */
		video_release(splash->video);
		video_unlock(splash->video);

		if (dbus != NULL) {
			do {
				*dbus = dbus_init();
				usleep(DBUS_WAIT_DELAY);
			} while (*dbus == NULL);
			splash_set_dbus(splash, *dbus);
		}
		fd = open("/sys/kernel/debug/dri/drm_master_relax", O_WRONLY);
		if (fd != -1) {
			num_written = write(fd, "Y", 1);
			close(fd);

			/*
			 * If we can't set drm_master relax, then transitions between chrome
			 * and frecon won't work.  No point in having frecon hold any resources
			 */
			if (num_written != 1) {
				LOG(ERROR, "Unable to set drm_master_relax");
				splash->devmode = false;
			}
		} else {
			LOG(ERROR, "unable to open drm_master_relax");
		}
	} else {
		/*
		 * Below, we will wait for Chrome to appear above the splash
		 * image.  If we are not in dev mode, wait and then exit
		 */
		sleep(MAX_SPLASH_WAITTIME);
		exit(EXIT_SUCCESS);
	}

	if (splash->dbus) {
		(void)dbus_method_call0(splash->dbus,
			kLibCrosServiceName,
			kLibCrosServicePath,
			kLibCrosServiceInterface,
			kTakeDisplayOwnership);
	}

	/*
	 * Finally, wait until chrome has drawn on top of the splash.  In dev mode,
	 * wait a few seconds for chrome to show up.
	 */
	sleep(MAX_SPLASH_WAITTIME);
	return status;
}

void splash_set_offset(splash_t* splash, int32_t x, int32_t y)
{
	if (splash) {
		splash->offset_x = x;
		splash->offset_y = y;
	}
}

void splash_set_dbus(splash_t* splash, dbus_t* dbus)
{
	if (splash)
		splash->dbus = dbus;
}

void splash_set_devmode(splash_t* splash)
{
	if (splash)
		splash->devmode = true;
}

int splash_num_images(splash_t *splash)
{
	if (splash)
		return splash->num_images;

	return 0;
}

void splash_set_default_duration(splash_t* splash, uint32_t duration)
{
	if (splash)
		splash->default_duration = duration;
}

void splash_set_loop_start(splash_t* splash, int32_t loop_start)
{
	if (splash)
		splash->loop_start = loop_start;
}

void splash_set_loop_duration(splash_t* splash, uint32_t duration)
{
	if (splash)
		splash->loop_duration = duration;
}

void splash_set_loop_offset(splash_t* splash, int32_t x, int32_t y)
{
	if (splash) {
		splash->loop_offset_x = x;
		splash->loop_offset_y = y;
	}
}

void splash_present_term_file(splash_t* splash)
{
	fprintf(stdout, "%s\n", term_get_ptsname(splash->terminal));
}
